@yannick-z/modulo 0.3.1 → 0.3.3

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/938.js ADDED
@@ -0,0 +1,289 @@
1
+ import { cwd, exit } from "node:process";
2
+ import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import { debug_log, readFileSync, readdirSync, resolve, existsSync, statSync, picocolors, writeFileSync, join } from "./131.js";
4
+ function read_file(path, error_msg, throwError = false) {
5
+ try {
6
+ return readFileSync(path, "utf8");
7
+ } catch (error) {
8
+ const msg = error_msg || `文件无法访问或者不存在: ${path}`;
9
+ debug_log("read_file error", msg, error);
10
+ if (throwError) throw new Error(msg);
11
+ console.log(picocolors.red(msg));
12
+ return "";
13
+ }
14
+ }
15
+ function resolve_and_read(root, name) {
16
+ const fullpath = resolve(root, name);
17
+ debug_log(`resolve file: ${name}`, "result is:", fullpath);
18
+ return read_file(fullpath);
19
+ }
20
+ function get_directories(path) {
21
+ try {
22
+ if (!existsSync(path)) return [];
23
+ return readdirSync(path).filter((file)=>{
24
+ const fullPath = join(path, file);
25
+ return statSync(fullPath).isDirectory();
26
+ });
27
+ } catch (error) {
28
+ debug_log("get_directories error", path, error);
29
+ return [];
30
+ }
31
+ }
32
+ function find_entry_file(dir, candidates, extensions = [
33
+ ".ts",
34
+ ".tsx",
35
+ ".js",
36
+ ".jsx",
37
+ ".vue"
38
+ ]) {
39
+ for (const name of candidates)for (const ext of extensions){
40
+ const filename = `${name}${ext}`;
41
+ const filepath = join(dir, filename);
42
+ if (existsSync(filepath) && statSync(filepath).isFile()) return filepath;
43
+ }
44
+ }
45
+ function exists(path) {
46
+ const isExist = existsSync(path);
47
+ debug_log(`check exists: ${path}`, isExist);
48
+ return isExist;
49
+ }
50
+ function jsonparse(input, defaultValue) {
51
+ try {
52
+ if (input) return JSON.parse(input);
53
+ return defaultValue;
54
+ } catch (e) {
55
+ console.error(picocolors.red(`JSON.parse failed\n${e}`));
56
+ return defaultValue;
57
+ }
58
+ }
59
+ function update_json_file(path, updater, createIfNotExist = false) {
60
+ try {
61
+ let data;
62
+ try {
63
+ const content = readFileSync(path, "utf-8");
64
+ const parsed = jsonparse(content);
65
+ if (parsed) data = parsed;
66
+ else if (createIfNotExist) data = {};
67
+ else {
68
+ console.error(picocolors.red(`Failed to parse JSON file: ${path}`));
69
+ return false;
70
+ }
71
+ } catch (error) {
72
+ if ("ENOENT" === error.code && createIfNotExist) data = {};
73
+ else {
74
+ console.error(picocolors.red(`Failed to read file: ${path}`));
75
+ return false;
76
+ }
77
+ }
78
+ const newData = updater(data);
79
+ writeFileSync(path, JSON.stringify(newData, null, 2) + "\n");
80
+ return true;
81
+ } catch (e) {
82
+ console.error(picocolors.red(`Failed to update JSON file: ${path}\n${e}`));
83
+ return false;
84
+ }
85
+ }
86
+ const panic_alert = "! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !";
87
+ function PANIC_IF(status = false, msg = "SOMETHING'S WRONG", halt = true) {
88
+ if (status) {
89
+ console.log(picocolors.bgRed(picocolors.white(`\n${panic_alert}\n\n${msg}\n\n${panic_alert}`)), "\n");
90
+ halt && exit(1);
91
+ }
92
+ }
93
+ function merge_user_config(target, input) {
94
+ for(const key in input){
95
+ const from = input[key];
96
+ const to = target[key];
97
+ if (typeof from === typeof to && key in target) if (Array.isArray(to)) {
98
+ PANIC_IF(!Array.isArray(from));
99
+ target[key] = [
100
+ ...to,
101
+ ...from
102
+ ];
103
+ } else if ("object" == typeof to) merge_user_config(to, from);
104
+ else target[key] = from;
105
+ else {
106
+ target[key] = from;
107
+ continue;
108
+ }
109
+ }
110
+ }
111
+ const preset_alias = {
112
+ "@": "{input.src}"
113
+ };
114
+ const preset_dev_server_config = {
115
+ open: false,
116
+ port: 8080,
117
+ proxy: {}
118
+ };
119
+ const preset_input_dirs = {
120
+ src: "src",
121
+ pages: "pages",
122
+ modules: "modules"
123
+ };
124
+ const preset_output_dirs = {
125
+ dist: "dist",
126
+ pages: "",
127
+ modules: "modules",
128
+ filenameHash: true
129
+ };
130
+ const default_html_config = {
131
+ meta: {},
132
+ root: "",
133
+ tags: [],
134
+ template: "",
135
+ title: ""
136
+ };
137
+ const preset_ui_libs = {
138
+ react19: "19.2.4",
139
+ vue2: "2.7.16"
140
+ };
141
+ const preset_minify_config = {
142
+ js: true,
143
+ jsOptions: {
144
+ minimizerOptions: {
145
+ compress: {
146
+ dead_code: true,
147
+ defaults: false,
148
+ toplevel: true,
149
+ unused: true
150
+ },
151
+ format: {
152
+ comments: "some",
153
+ ecma: 2015,
154
+ preserve_annotations: true,
155
+ safari10: true,
156
+ semicolons: false
157
+ },
158
+ mangle: true,
159
+ minify: true
160
+ }
161
+ }
162
+ };
163
+ const preset_url_config = {
164
+ base: "/",
165
+ cdn: ""
166
+ };
167
+ const preset_config = {
168
+ analyze: false,
169
+ define: {},
170
+ dev_server: preset_dev_server_config,
171
+ externals: {},
172
+ html: default_html_config,
173
+ input: preset_input_dirs,
174
+ minify: preset_minify_config,
175
+ output: preset_output_dirs,
176
+ ui_lib: preset_ui_libs,
177
+ url: preset_url_config,
178
+ alias: preset_alias,
179
+ webhost: true,
180
+ autoExternal: true,
181
+ externalsType: "importmap"
182
+ };
183
+ const config_root = cwd();
184
+ let packagejson = null;
185
+ function get_packagejson(customRoot = config_root) {
186
+ if (packagejson) {
187
+ if (customRoot !== config_root) {
188
+ const newPackageJson = jsonparse(resolve_and_read(customRoot, "package.json"));
189
+ PANIC_IF(!newPackageJson, "根目录下没有package.json");
190
+ PANIC_IF(!newPackageJson.name, "package.json缺少name字段");
191
+ return newPackageJson;
192
+ }
193
+ } else {
194
+ packagejson = jsonparse(resolve_and_read(customRoot, "package.json"));
195
+ PANIC_IF(!packagejson, "根目录下没有package.json");
196
+ PANIC_IF(!packagejson.name, "package.json缺少name字段");
197
+ }
198
+ return packagejson;
199
+ }
200
+ let global_config;
201
+ async function get_global_config(args) {
202
+ if (!global_config) {
203
+ let configPath = args.pack.config;
204
+ if (!configPath) {
205
+ const candidates = [
206
+ "modulo.config.ts",
207
+ "modulo.config.js",
208
+ "modulo.config.json"
209
+ ];
210
+ for (const f of candidates){
211
+ const p = resolve(config_root, f);
212
+ if (existsSync(p)) {
213
+ configPath = p;
214
+ break;
215
+ }
216
+ }
217
+ }
218
+ if (!configPath) throw new Error("根目录下没有配置文件 (modulo.config.ts/js/json)");
219
+ const resolvedConfigPath = resolve(config_root, configPath);
220
+ let user_config;
221
+ try {
222
+ const fileUrl = pathToFileURL(resolvedConfigPath).href;
223
+ const mod = await import(fileUrl);
224
+ user_config = mod.default || mod;
225
+ } catch (e) {
226
+ console.error(`无法加载配置文件: ${resolvedConfigPath}`);
227
+ throw e;
228
+ }
229
+ PANIC_IF(!user_config, "根目录下没有配置文件");
230
+ debug_log("input user config", user_config);
231
+ if (user_config.extends) {
232
+ const extend_config_path = resolve(config_root, user_config.extends);
233
+ try {
234
+ const extend_fileUrl = pathToFileURL(extend_config_path).href;
235
+ const extend_mod = await import(extend_fileUrl);
236
+ const extend_config = extend_mod.default || extend_mod;
237
+ debug_log("extend config", extend_config);
238
+ merge_user_config(preset_config, extend_config);
239
+ } catch (e) {
240
+ console.error(`无法加载继承的配置文件: ${extend_config_path}`);
241
+ throw e;
242
+ }
243
+ }
244
+ merge_user_config(preset_config, user_config);
245
+ const _config = preset_config;
246
+ const src = resolve(config_root, _config.input.src);
247
+ const input = {
248
+ modules: resolve(src, _config.input.modules),
249
+ pages: resolve(src, _config.input.pages),
250
+ src: src
251
+ };
252
+ const dist = resolve(config_root, _config.output.dist);
253
+ const output = {
254
+ ..._config.output,
255
+ dist: dist,
256
+ modules: resolve(dist, _config.output.modules),
257
+ pages: resolve(dist, _config.output.pages)
258
+ };
259
+ const html = _config.html?.template ? {
260
+ ..._config.html,
261
+ template: resolve(config_root, _config.html.template)
262
+ } : _config.html;
263
+ const define = Object.fromEntries(Object.entries({
264
+ ..._config.define,
265
+ "import.meta.env.MOUNT_ID": _config.html.root
266
+ }).map(([k, v])=>[
267
+ k,
268
+ JSON.stringify(v)
269
+ ]));
270
+ debug_log("当前模式", process.env.NODE_ENV);
271
+ const minify = true === _config.minify ? preset_minify_config : _config.minify;
272
+ const alias = Object.fromEntries(Object.entries(_config.alias).map(([k, v])=>[
273
+ k,
274
+ v.replace("{input.src}", input.src)
275
+ ]));
276
+ global_config = {
277
+ ..._config,
278
+ define,
279
+ html,
280
+ input,
281
+ minify,
282
+ output,
283
+ alias
284
+ };
285
+ debug_log("global config", global_config);
286
+ }
287
+ return global_config;
288
+ }
289
+ export { PANIC_IF, exists, fileURLToPath, find_entry_file, get_directories, get_global_config, get_packagejson, preset_alias, preset_config, update_json_file };
@@ -0,0 +1,15 @@
1
+ #! /usr/bin/env node
2
+ import("../131.js").then((mod)=>({
3
+ exec: mod.exec
4
+ })).then((module)=>{
5
+ try {
6
+ module.exec();
7
+ } catch (e) {
8
+ console.error(e);
9
+ process.exit(1);
10
+ }
11
+ }).catch((e)=>{
12
+ console.error("\x1b[31mError: Failed to load modulo.\x1b[0m");
13
+ console.error(e);
14
+ process.exit(1);
15
+ });
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { exec } from "./131.js";
package/package.json CHANGED
@@ -2,18 +2,25 @@
2
2
  "name": "@yannick-z/modulo",
3
3
  "description": "",
4
4
  "type": "module",
5
- "version": "0.3.1",
6
- "main": "./src/index.ts",
5
+ "version": "0.3.3",
6
+ "main": "./dist/index.js",
7
7
  "author": "oyangxiao",
8
8
  "scripts": {
9
- "build": "直接使用ts执行,所以不需要build",
10
- "lint": "biome lint .",
11
- "format": "biome format --write .",
12
- "check": "biome check --write ."
9
+ "build": "rslib build",
10
+ "lint": "biome lint src bin rslib.config.ts",
11
+ "format": "biome format --write src bin rslib.config.ts package.json biome.json",
12
+ "check": "biome check --write src bin rslib.config.ts package.json biome.json"
13
13
  },
14
14
  "bin": {
15
- "modulo": "./bin/modulo.js"
15
+ "modulo": "./dist/bin/modulo.js"
16
16
  },
17
+ "files": [
18
+ "dist",
19
+ "bin",
20
+ "src",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
17
24
  "dependencies": {
18
25
  "@rsbuild/core": "^1.7.3",
19
26
  "@rsbuild/plugin-less": "^1.6.0",
@@ -0,0 +1,16 @@
1
+ #! /usr/bin/env node
2
+
3
+ import("../index.js")
4
+ .then((module) => {
5
+ try {
6
+ module.exec();
7
+ } catch (e) {
8
+ console.error(e);
9
+ process.exit(1);
10
+ }
11
+ })
12
+ .catch((e) => {
13
+ console.error("\x1b[31mError: Failed to load modulo.\x1b[0m");
14
+ console.error(e);
15
+ process.exit(1);
16
+ });
@@ -1,5 +1,4 @@
1
1
  import { createRequire } from 'node:module';
2
- import type { Compiler, Compilation } from "@rspack/core";
3
2
  const require = createRequire(import.meta.url);
4
3
  import type { ModuloArgs_Pack } from "../args/index.ts";
5
4
  import type { GLOBAL_CONFIG } from "../config/type.ts";
@@ -25,12 +24,12 @@ export class AutoExternalPlugin {
25
24
  this.usedExternals = new Set<string>();
26
25
  }
27
26
 
28
- apply(compiler: Compiler) {
27
+ apply(compiler: any) {
29
28
  compiler.hooks.compilation.tap(
30
29
  "AutoExternalPlugin",
31
- (compilation: Compilation) => {
30
+ (compilation: any) => {
32
31
  // 1. 扫描模块依赖
33
- compilation.hooks.finishModules.tap("AutoExternalPlugin", (modules) => {
32
+ compilation.hooks.finishModules.tap("AutoExternalPlugin", (modules: any[]) => {
34
33
  // ... (省略模块扫描逻辑,这里没有问题) ...
35
34
  for (const module of modules) {
36
35
  // @ts-ignore
@@ -86,7 +85,7 @@ export class AutoExternalPlugin {
86
85
  // 或者我们可以尝试直接使用 tapAsync 到 HtmlWebpackPlugin 的实例上,如果我们能找到它
87
86
 
88
87
  // 终极 Hook 调试: 使用 compiler.hooks.emit 来检查 assets,看是否包含 index.html,以及内容
89
- compiler.hooks.emit.tapAsync("AutoExternalPlugin", (compilation, cb) => {
88
+ compiler.hooks.emit.tapAsync("AutoExternalPlugin", (compilation: any, cb: any) => {
90
89
  if (process.env.DEBUG) console.log('[AutoExternalPlugin] emit hook triggered');
91
90
  // 检查 compilation.assets
92
91
  const assetNames = Object.keys(compilation.assets);
@@ -7,7 +7,6 @@ import {
7
7
  import {
8
8
  is_env_external,
9
9
  is_string,
10
- is_import_external,
11
10
  } from "../type/guard.ts";
12
11
 
13
12
  function getExternalUrl(args: ModuloArgs_Pack, url: ConfigExternalUrl) {
@@ -61,7 +60,9 @@ export function getExternalsAndImportMap(
61
60
  const globalVar = externalLib.global || libName;
62
61
  const importName = externalLib.importName || libName;
63
62
  (Array.isArray(importName) ? importName : [importName]).forEach(
64
- (name) => (externals[name] = globalVar),
63
+ (name) => {
64
+ externals[name] = globalVar;
65
+ },
65
66
  );
66
67
 
67
68
  if (url) {
@@ -71,7 +72,9 @@ export function getExternalsAndImportMap(
71
72
  // Importmap 模式:external 映射为包名(由 importmap 解析)
72
73
  const importName = externalLib.importName || libName;
73
74
  (Array.isArray(importName) ? importName : [importName]).forEach(
74
- (name) => (externals[name] = libName),
75
+ (name) => {
76
+ externals[name] = libName;
77
+ },
75
78
  );
76
79
 
77
80
  if (url) {
package/src/packer/lib.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { pluginLess } from "@rsbuild/plugin-less";
2
- import * as rslib from "@rslib/core";
2
+ import { rsbuild, defineConfig, createRslib } from "@rslib/core";
3
3
  import picocolors from "picocolors";
4
4
  import type { ModuloArgs_Pack } from "../args/index.ts";
5
5
  import { get_global_config, get_packagejson } from "../config/index.ts";
@@ -23,7 +23,8 @@ export async function lib_pack(args: ModuloArgs_Pack) {
23
23
  return;
24
24
  }
25
25
 
26
- const rslibConfig = rslib.defineConfig({
26
+ const rslibConfig = defineConfig({
27
+ root: process.cwd(),
27
28
  source: {
28
29
  define: config.define,
29
30
  entry: entries,
@@ -83,8 +84,10 @@ export async function lib_pack(args: ModuloArgs_Pack) {
83
84
  },
84
85
  });
85
86
 
86
- const { build } = await rslib.createRslib({ config: rslibConfig });
87
- await build({ watch: args.cmd === "build" && args.pack.watch });
87
+ const rslibInstance = await createRslib({ config: rslibConfig })
88
+ await rslibInstance.build({
89
+ watch: args.cmd === "build" && !!args.pack.watch,
90
+ });
88
91
 
89
92
  if (args.cmd === "build") {
90
93
  console.log(picocolors.green("\n**** 构建【module】完成 ****\n"));
@@ -1,3 +0,0 @@
1
- {
2
- "recommendations": ["biomejs.biome"]
3
- }
package/biome.json DELETED
@@ -1,34 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
3
- "vcs": {
4
- "enabled": false,
5
- "clientKind": "git",
6
- "useIgnoreFile": false
7
- },
8
- "files": {
9
- "ignoreUnknown": false
10
- },
11
- "formatter": {
12
- "enabled": true,
13
- "indentStyle": "tab"
14
- },
15
- "linter": {
16
- "enabled": true,
17
- "rules": {
18
- "recommended": true
19
- }
20
- },
21
- "javascript": {
22
- "formatter": {
23
- "quoteStyle": "double"
24
- }
25
- },
26
- "assist": {
27
- "enabled": true,
28
- "actions": {
29
- "source": {
30
- "organizeImports": "on"
31
- }
32
- }
33
- }
34
- }
package/rslib.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import { defineConfig } from "@rslib/core";
2
-
3
- export default defineConfig({
4
- lib: [
5
- {
6
- dts: false,
7
- format: "esm",
8
- syntax: "esnext",
9
- },
10
- ],
11
- output: {
12
- distPath: {
13
- root: "./dist",
14
- },
15
- target: "node",
16
- },
17
- source: {
18
- entry: {
19
- index: "./src/index.ts",
20
- },
21
- },
22
- });
@@ -1,12 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- </head>
7
-
8
- <body>
9
- <div id="<%= mountId %>"></div>
10
- </body>
11
-
12
- </html>
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowImportingTsExtensions": true,
4
- "allowJs": true,
5
- "noEmit": true,
6
- "outDir": "./dist",
7
- "rootDir": "./"
8
- },
9
- "extends": "../../tsconfig.base.json",
10
- "include": ["./src/**/*", "./rslib.config.ts", "./types/*"]
11
- }