ptech-preset 1.2.4 → 1.2.6

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.d.ts CHANGED
@@ -13,6 +13,10 @@ type MfAutoOptions = {
13
13
  stylesExposeKey?: string;
14
14
  separateExposes?: boolean;
15
15
  separateExposeChunkPrefix?: string;
16
+ /** tên folder chứa types đã consume; mặc định "@mf-types" */
17
+ typesFolder?: string;
18
+ /** env để ép refresh types ở dev (khởi động lại dev) */
19
+ devTypesRefreshEnvVar?: string;
16
20
  mf: Record<string, any>;
17
21
  };
18
22
  declare function pluginCore(opts: MfAutoOptions): RsbuildPlugin;
package/dist/index.js CHANGED
@@ -17,10 +17,7 @@ async function collectAutoExposes(opts = {}) {
17
17
  absolute: true,
18
18
  ignore: ["**/*.d.ts"]
19
19
  });
20
- const jsdocRe = new RegExp(
21
- String.raw`/\*\*[\s\S]*?@${tag}(?:\s+([^\s*]+))?[\s\S]*?\*/`,
22
- "m"
23
- );
20
+ const jsdocRe = new RegExp(String.raw`/\*\*[\s\S]*?@${tag}(?:\s+([^\s*]+))?[\s\S]*?\*/`, "m");
24
21
  const exposes = {};
25
22
  const root = process.cwd();
26
23
  for (const abs of files) {
@@ -50,10 +47,7 @@ async function collectAutoExposesWithWrapper(opts = {}) {
50
47
  ignore: ["**/*.d.ts"]
51
48
  });
52
49
  const root = process.cwd();
53
- const jsdocRe = new RegExp(
54
- String.raw`/\*\*[\s\S]*?@expose(?:\s+([^\s*]+))?[\s\S]*?\*/`,
55
- "m"
56
- );
50
+ const jsdocRe = new RegExp(String.raw`/\*\*[\s\S]*?@expose(?:\s+([^\s*]+))?[\s\S]*?\*/`, "m");
57
51
  const wrapperRe = /exposeComponent\s*\(\s*[^,]+,\s*['"`]([^'"`]+)['"`]\s*\)/;
58
52
  const exposes = {};
59
53
  for (const abs of files) {
@@ -74,7 +68,9 @@ async function collectAutoExposesWithWrapper(opts = {}) {
74
68
  }
75
69
  }
76
70
  if (debug) {
77
- console.log(`[mf-auto] collectAutoExposesWithWrapper: ${Object.keys(exposes).length} expose(s) found`);
71
+ console.log(
72
+ `[mf-auto] collectAutoExposesWithWrapper: ${Object.keys(exposes).length} expose(s) found`
73
+ );
78
74
  }
79
75
  return exposes;
80
76
  }
@@ -85,10 +81,12 @@ import path2 from "path";
85
81
  async function collectAutoRemotes(opts = {}) {
86
82
  const remotes = {};
87
83
  const prefix = opts.envPrefix ?? "REMOTE_";
88
- for (const [k, v] of Object.entries(process.env)) {
89
- if (!v) continue;
84
+ for (const [k, vRaw] of Object.entries(process.env)) {
85
+ if (!vRaw) continue;
90
86
  if (k.startsWith(prefix)) {
91
87
  const scope = k.slice(prefix.length).toLowerCase();
88
+ const v = String(vRaw).trim();
89
+ if (!v) continue;
92
90
  remotes[scope] = `${scope}@${v}`;
93
91
  }
94
92
  }
@@ -115,9 +113,13 @@ async function collectAutoRemotes(opts = {}) {
115
113
  console.warn(`[mf-auto] read manifest error:`, e);
116
114
  }
117
115
  }
118
- for (const [scope, url] of Object.entries(obj)) {
119
- if (typeof url === "string" && url.trim()) {
120
- remotes[scope] = `${scope}@${url}`;
116
+ for (const [scopeRaw, urlRaw] of Object.entries(obj)) {
117
+ const scope = String(scopeRaw).toLowerCase();
118
+ const url = String(urlRaw || "").trim();
119
+ if (url) {
120
+ if (!remotes[scope]) {
121
+ remotes[scope] = `${scope}@${url}`;
122
+ }
121
123
  }
122
124
  }
123
125
  }
@@ -154,6 +156,75 @@ var DEFAULT_SHARED = {
154
156
  "@azure/msal-browser": { singleton: true, eager: true, requiredVersion: false }
155
157
  };
156
158
  var CDN_BASE = "https://oneportal.blob.core.windows.net/external/ts/";
159
+ function parseRemoteSpec(key, val) {
160
+ if (typeof val !== "string") return null;
161
+ const m = val.match(/^([^@]+)@(.+)$/);
162
+ if (m) return { scope: m[1], url: m[2] };
163
+ return { scope: key, url: val };
164
+ }
165
+ function inferTypeUrls(remoteUrl) {
166
+ if (typeof remoteUrl !== "string") return null;
167
+ const base = remoteUrl.replace(/\/remoteEntry(\.[cm]?js)?(\?.*)?$/i, "");
168
+ const b = base && base !== remoteUrl ? base : (() => {
169
+ const i = remoteUrl.lastIndexOf("/");
170
+ return i > 7 ? remoteUrl.slice(0, i) : remoteUrl;
171
+ })();
172
+ return { base: b, zip: `${b}/@mf-types.zip`, api: `${b}/@mf-types.d.ts` };
173
+ }
174
+ function buildRemoteTypeUrls(remotes) {
175
+ const out = {};
176
+ if (!remotes || typeof remotes !== "object") return out;
177
+ for (const [key, val] of Object.entries(remotes)) {
178
+ if (typeof val !== "string") continue;
179
+ const parsed = parseRemoteSpec(key, val);
180
+ if (!parsed) continue;
181
+ const t = inferTypeUrls(parsed.url);
182
+ if (!t) continue;
183
+ const scope = (parsed.scope || key).toString();
184
+ out[scope] = { alias: scope, zip: t.zip, api: t.api };
185
+ }
186
+ return out;
187
+ }
188
+ function ensureDtsObject(dts) {
189
+ if (dts === false) return false;
190
+ if (dts == null || dts === true) return {};
191
+ if (typeof dts === "object") return { ...dts };
192
+ return {};
193
+ }
194
+ async function devFetchRemoteTypesOnce(params) {
195
+ const { root, baseDir, typesFolderRel, urls } = params;
196
+ if (!urls || Object.keys(urls).length === 0) return;
197
+ const typesRootAbs = path3.resolve(root, typesFolderRel);
198
+ const remDir = path3.join(typesRootAbs, "__remotes");
199
+ fs3.mkdirSync(remDir, { recursive: true });
200
+ for (const [scope, spec] of Object.entries(urls)) {
201
+ try {
202
+ const res = await fetch(spec.api);
203
+ if (!res.ok) {
204
+ console.warn(`[mf-auto] fetch types failed for ${scope}: ${res.status} ${res.statusText}`);
205
+ continue;
206
+ }
207
+ const txt = await res.text();
208
+ fs3.writeFileSync(path3.join(remDir, `${scope}.d.ts`), txt, "utf8");
209
+ } catch (e) {
210
+ console.warn(`[mf-auto] fetch types error for ${scope}:`, e);
211
+ }
212
+ }
213
+ const refs = Object.keys(urls).map((s) => `/// <reference path="./__remotes/${s}.d.ts" />`).join(os.EOL);
214
+ const banner = `// generated by plugin-mf-auto (dev once)
215
+ `;
216
+ fs3.writeFileSync(path3.join(typesRootAbs, "index.d.ts"), banner + refs + os.EOL, "utf8");
217
+ const shimDir = path3.join(root, baseDir, ".mf-auto");
218
+ fs3.mkdirSync(shimDir, { recursive: true });
219
+ const relToIndex = path3.relative(shimDir, path3.join(typesRootAbs, "index.d.ts")).replace(/\\/g, "/");
220
+ fs3.writeFileSync(
221
+ path3.join(shimDir, "mf-types.d.ts"),
222
+ `/// <reference path="${relToIndex}" />
223
+ // generated by plugin-mf-auto
224
+ `,
225
+ "utf8"
226
+ );
227
+ }
157
228
  function pluginCore(opts) {
158
229
  const {
159
230
  baseDir = "src",
@@ -167,6 +238,8 @@ function pluginCore(opts) {
167
238
  stylesExposeKey = "./styles",
168
239
  separateExposes = true,
169
240
  separateExposeChunkPrefix = "mf-expose-",
241
+ typesFolder = "@mf-types",
242
+ devTypesRefreshEnvVar = "MF_DTS_REFRESH",
170
243
  mf
171
244
  } = opts;
172
245
  if (!mf || typeof mf !== "object") {
@@ -249,18 +322,60 @@ function pluginCore(opts) {
249
322
  mfMerged.exposes = { ...mfMerged.exposes ?? {}, [stylesExposeKey]: `./${relFromRoot}` };
250
323
  }
251
324
  }
252
- const isBuild = api?.context?.command === "build" || process.env.NODE_ENV === "production";
253
- if (typeof mfMerged.dts === "undefined") {
254
- mfMerged.dts = isBuild;
325
+ const command = api?.context?.command;
326
+ const isProd = process.env.NODE_ENV === "production" || command === "build";
327
+ const isDev = !isProd;
328
+ const autoTypeUrls = buildRemoteTypeUrls(mfMerged.remotes || {});
329
+ if (isDev) {
330
+ const refresh = process.env[devTypesRefreshEnvVar] === "1";
331
+ const typesRootAbs = path3.resolve(root, typesFolder);
332
+ const indexFile = path3.join(typesRootAbs, "index.d.ts");
333
+ const needFetch = refresh || !fs3.existsSync(indexFile) || Object.keys(autoTypeUrls).some(
334
+ (s) => !fs3.existsSync(path3.join(typesRootAbs, "__remotes", `${s}.d.ts`))
335
+ );
336
+ if (Object.keys(autoTypeUrls).length > 0) {
337
+ if (needFetch) {
338
+ await devFetchRemoteTypesOnce({
339
+ root,
340
+ baseDir,
341
+ typesFolderRel: typesFolder,
342
+ urls: autoTypeUrls
343
+ });
344
+ }
345
+ const dtsObj = ensureDtsObject(mfMerged.dts);
346
+ dtsObj.generateTypes = dtsObj.generateTypes ?? { tsConfigPath: "./tsconfig.json" };
347
+ mfMerged.dts = dtsObj;
348
+ } else {
349
+ const dtsObj = ensureDtsObject(mfMerged.dts);
350
+ dtsObj.generateTypes = dtsObj.generateTypes ?? { tsConfigPath: "./tsconfig.json" };
351
+ mfMerged.dts = dtsObj;
352
+ }
353
+ } else {
354
+ if (mfMerged.dts !== false) {
355
+ const dtsObj = ensureDtsObject(mfMerged.dts);
356
+ if (Object.keys(autoTypeUrls).length > 0) {
357
+ const existingConsume = dtsObj.consumeTypes ?? {};
358
+ const existingRt = existingConsume.remoteTypeUrls ?? {};
359
+ dtsObj.consumeTypes = {
360
+ typesFolder: existingConsume.typesFolder ?? typesFolder,
361
+ maxRetries: existingConsume.maxRetries ?? 3,
362
+ // ưu tiên config hiện hữu nếu đụng key
363
+ remoteTypeUrls: { ...autoTypeUrls, ...existingRt }
364
+ };
365
+ }
366
+ dtsObj.generateTypes = dtsObj.generateTypes ?? { tsConfigPath: "./tsconfig.json" };
367
+ mfMerged.dts = dtsObj;
368
+ }
255
369
  }
256
370
  const mfPlugin = pluginModuleFederation(mfMerged);
257
371
  await mfPlugin.setup?.(api);
258
372
  const pkgSafe = getPackageName(root) || mfMerged.name || path3.basename(root).replace(/\W+/g, "");
259
373
  const cdnUrl = `${CDN_BASE}${pkgSafe}/`;
260
- const isProd = process.env.NODE_ENV === "production";
261
374
  api.modifyRsbuildConfig((config) => {
262
375
  config.output ??= {};
263
- if (isProd && !config.output.assetPrefix) config.output.assetPrefix = cdnUrl;
376
+ if (!config.output.assetPrefix && process.env.NODE_ENV === "production") {
377
+ config.output.assetPrefix = cdnUrl;
378
+ }
264
379
  return config;
265
380
  });
266
381
  if (separateExposes && mfMerged.exposes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ptech-preset",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "Auto Module.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",