@fulgurjs/federation 0.4.2 → 0.5.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/pages.cjs CHANGED
@@ -20,8 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/pages.ts
21
21
  var pages_exports = {};
22
22
  __export(pages_exports, {
23
- defineFulgurPages: () => defineFulgurPages,
24
- validateFulgurPages: () => validateFulgurPages
23
+ defineFulgurjsPages: () => defineFulgurjsPages,
24
+ validateFulgurjsPages: () => validateFulgurjsPages
25
25
  });
26
26
  module.exports = __toCommonJS(pages_exports);
27
27
  var normSpec = (s) => s.replace(/^[./]+/, "").replace(/\/+$/, "");
@@ -53,7 +53,7 @@ function remoteOfRoute(route, remotes) {
53
53
  }
54
54
  return null;
55
55
  }
56
- function validateFulgurPages(pages, options = {}) {
56
+ function validateFulgurjsPages(pages, options = {}) {
57
57
  const deriveSpec = options.deriveSpec ?? defaultDeriveSpec;
58
58
  const violations = [];
59
59
  const effective = pages.map((p) => normSpec(p.spec ?? deriveSpec(p.route)));
@@ -140,17 +140,17 @@ function formatViolations(violations) {
140
140
  const warns = violations.filter((v) => v.level === "warn");
141
141
  let out = "";
142
142
  if (errors.length) {
143
- out += `[fulgur] \u8DEF\u7531\u8868\u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u9879\uFF0CERROR\uFF09\uFF1A
143
+ out += `[fulgurjs] \u8DEF\u7531\u8868\u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u9879\uFF0CERROR\uFF09\uFF1A
144
144
  ` + errors.map((v) => v.message).join("\n") + "\n";
145
145
  }
146
146
  if (warns.length) {
147
- out += `[fulgur] \u8DEF\u7531\u8868\u6821\u9A8C\u8B66\u544A\uFF08${warns.length} \u9879\uFF0CWARN\uFF09\uFF1A
147
+ out += `[fulgurjs] \u8DEF\u7531\u8868\u6821\u9A8C\u8B66\u544A\uFF08${warns.length} \u9879\uFF0CWARN\uFF09\uFF1A
148
148
  ` + warns.map((v) => v.message).join("\n");
149
149
  }
150
150
  return out.trim();
151
151
  }
152
- function defineFulgurPages(pages, options = {}) {
153
- const violations = validateFulgurPages(pages, options);
152
+ function defineFulgurjsPages(pages, options = {}) {
153
+ const violations = validateFulgurjsPages(pages, options);
154
154
  const errors = violations.filter((v) => v.level === "error");
155
155
  const warns = violations.filter((v) => v.level === "warn");
156
156
  const text = formatViolations(violations);
@@ -164,6 +164,6 @@ function defineFulgurPages(pages, options = {}) {
164
164
  }
165
165
  // Annotate the CommonJS export names for ESM import in node:
166
166
  0 && (module.exports = {
167
- defineFulgurPages,
168
- validateFulgurPages
167
+ defineFulgurjsPages,
168
+ validateFulgurjsPages
169
169
  });
package/dist/pages.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * D.2 宿主路由表校验器(defineFulgurPages)
2
+ * D.2 宿主路由表校验器(defineFulgurjsPages)
3
3
  *
4
4
  * 背景:带参路由缺省推导 spec 时会剥离 :参数 段,可能与其它条目(如列表页)的
5
5
  * expose 键收敛相同 → 静默加载错误组件(真实事故:复制流程误走更新语义)。
@@ -17,7 +17,7 @@
17
17
  * 含路由完全重复
18
18
  * - R5 [WARN] name 字段重复(vue-router 命名跳转歧义)
19
19
  */
20
- interface FulgurPageRouteLike {
20
+ interface FulgurjsPageRouteLike {
21
21
  /** 宿主路由路径(:param 段) */
22
22
  route: string;
23
23
  /** 显式 spec(缺省走推导) */
@@ -32,7 +32,7 @@ interface RemoteSchemaEntry {
32
32
  /** manifest 是否成功拉取(false 时跳过该 remote 的 R3,诚实降级) */
33
33
  exists?: boolean;
34
34
  }
35
- interface FulgurPagesOptions {
35
+ interface FulgurjsPagesOptions {
36
36
  /**
37
37
  * 带参路由的缺省 spec 推导规则(宿主私有约定,如
38
38
  * (route) => `pages/${route 去前缀去 :参}`)。
@@ -42,7 +42,7 @@ interface FulgurPagesOptions {
42
42
  deriveSpec?: (route: string) => string;
43
43
  /** 路由前缀 → remote 名(R3 用:{'/remote-a/': 'remote-a'});缺省跳过 R3 */
44
44
  remotes?: Record<string, string>;
45
- /** remote exposes 清单(dev 由 virtual:fulgur-remote-schema 提供);缺省跳过 R3 */
45
+ /** remote exposes 清单(dev 由 virtual:fulgurjs-remote-schema 提供);缺省跳过 R3 */
46
46
  schema?: Record<string, RemoteSchemaEntry>;
47
47
  /** false = ERROR 降级 console.error(默认 true = throw) */
48
48
  strict?: boolean;
@@ -55,12 +55,12 @@ interface PageViolation {
55
55
  /**
56
56
  * 校验路由表(独立导出便于单测):返回违例清单(不抛错)。
57
57
  */
58
- declare function validateFulgurPages(pages: FulgurPageRouteLike[], options?: FulgurPagesOptions): PageViolation[];
58
+ declare function validateFulgurjsPages(pages: FulgurjsPageRouteLike[], options?: FulgurjsPagesOptions): PageViolation[];
59
59
  /**
60
60
  * 宿主路由表定义入口:校验(聚合报错)后原样返回入参,不改写任何字段。
61
61
  * 违反 ERROR 级规则时默认 throw(dev overlay / build 失败直接可见);
62
62
  * strict: false 时降级 console.error。WARN 级始终 console.warn。
63
63
  */
64
- declare function defineFulgurPages<P extends FulgurPageRouteLike[]>(pages: P, options?: FulgurPagesOptions): P;
64
+ declare function defineFulgurjsPages<P extends FulgurjsPageRouteLike[]>(pages: P, options?: FulgurjsPagesOptions): P;
65
65
 
66
- export { type FulgurPageRouteLike, type FulgurPagesOptions, type PageViolation, type RemoteSchemaEntry, defineFulgurPages, validateFulgurPages };
66
+ export { type FulgurjsPageRouteLike, type FulgurjsPagesOptions, type PageViolation, type RemoteSchemaEntry, defineFulgurjsPages, validateFulgurjsPages };
package/dist/pages.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * D.2 宿主路由表校验器(defineFulgurPages)
2
+ * D.2 宿主路由表校验器(defineFulgurjsPages)
3
3
  *
4
4
  * 背景:带参路由缺省推导 spec 时会剥离 :参数 段,可能与其它条目(如列表页)的
5
5
  * expose 键收敛相同 → 静默加载错误组件(真实事故:复制流程误走更新语义)。
@@ -17,7 +17,7 @@
17
17
  * 含路由完全重复
18
18
  * - R5 [WARN] name 字段重复(vue-router 命名跳转歧义)
19
19
  */
20
- interface FulgurPageRouteLike {
20
+ interface FulgurjsPageRouteLike {
21
21
  /** 宿主路由路径(:param 段) */
22
22
  route: string;
23
23
  /** 显式 spec(缺省走推导) */
@@ -32,7 +32,7 @@ interface RemoteSchemaEntry {
32
32
  /** manifest 是否成功拉取(false 时跳过该 remote 的 R3,诚实降级) */
33
33
  exists?: boolean;
34
34
  }
35
- interface FulgurPagesOptions {
35
+ interface FulgurjsPagesOptions {
36
36
  /**
37
37
  * 带参路由的缺省 spec 推导规则(宿主私有约定,如
38
38
  * (route) => `pages/${route 去前缀去 :参}`)。
@@ -42,7 +42,7 @@ interface FulgurPagesOptions {
42
42
  deriveSpec?: (route: string) => string;
43
43
  /** 路由前缀 → remote 名(R3 用:{'/remote-a/': 'remote-a'});缺省跳过 R3 */
44
44
  remotes?: Record<string, string>;
45
- /** remote exposes 清单(dev 由 virtual:fulgur-remote-schema 提供);缺省跳过 R3 */
45
+ /** remote exposes 清单(dev 由 virtual:fulgurjs-remote-schema 提供);缺省跳过 R3 */
46
46
  schema?: Record<string, RemoteSchemaEntry>;
47
47
  /** false = ERROR 降级 console.error(默认 true = throw) */
48
48
  strict?: boolean;
@@ -55,12 +55,12 @@ interface PageViolation {
55
55
  /**
56
56
  * 校验路由表(独立导出便于单测):返回违例清单(不抛错)。
57
57
  */
58
- declare function validateFulgurPages(pages: FulgurPageRouteLike[], options?: FulgurPagesOptions): PageViolation[];
58
+ declare function validateFulgurjsPages(pages: FulgurjsPageRouteLike[], options?: FulgurjsPagesOptions): PageViolation[];
59
59
  /**
60
60
  * 宿主路由表定义入口:校验(聚合报错)后原样返回入参,不改写任何字段。
61
61
  * 违反 ERROR 级规则时默认 throw(dev overlay / build 失败直接可见);
62
62
  * strict: false 时降级 console.error。WARN 级始终 console.warn。
63
63
  */
64
- declare function defineFulgurPages<P extends FulgurPageRouteLike[]>(pages: P, options?: FulgurPagesOptions): P;
64
+ declare function defineFulgurjsPages<P extends FulgurjsPageRouteLike[]>(pages: P, options?: FulgurjsPagesOptions): P;
65
65
 
66
- export { type FulgurPageRouteLike, type FulgurPagesOptions, type PageViolation, type RemoteSchemaEntry, defineFulgurPages, validateFulgurPages };
66
+ export { type FulgurjsPageRouteLike, type FulgurjsPagesOptions, type PageViolation, type RemoteSchemaEntry, defineFulgurjsPages, validateFulgurjsPages };
package/dist/pages.js CHANGED
@@ -28,7 +28,7 @@ function remoteOfRoute(route, remotes) {
28
28
  }
29
29
  return null;
30
30
  }
31
- function validateFulgurPages(pages, options = {}) {
31
+ function validateFulgurjsPages(pages, options = {}) {
32
32
  const deriveSpec = options.deriveSpec ?? defaultDeriveSpec;
33
33
  const violations = [];
34
34
  const effective = pages.map((p) => normSpec(p.spec ?? deriveSpec(p.route)));
@@ -115,17 +115,17 @@ function formatViolations(violations) {
115
115
  const warns = violations.filter((v) => v.level === "warn");
116
116
  let out = "";
117
117
  if (errors.length) {
118
- out += `[fulgur] \u8DEF\u7531\u8868\u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u9879\uFF0CERROR\uFF09\uFF1A
118
+ out += `[fulgurjs] \u8DEF\u7531\u8868\u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u9879\uFF0CERROR\uFF09\uFF1A
119
119
  ` + errors.map((v) => v.message).join("\n") + "\n";
120
120
  }
121
121
  if (warns.length) {
122
- out += `[fulgur] \u8DEF\u7531\u8868\u6821\u9A8C\u8B66\u544A\uFF08${warns.length} \u9879\uFF0CWARN\uFF09\uFF1A
122
+ out += `[fulgurjs] \u8DEF\u7531\u8868\u6821\u9A8C\u8B66\u544A\uFF08${warns.length} \u9879\uFF0CWARN\uFF09\uFF1A
123
123
  ` + warns.map((v) => v.message).join("\n");
124
124
  }
125
125
  return out.trim();
126
126
  }
127
- function defineFulgurPages(pages, options = {}) {
128
- const violations = validateFulgurPages(pages, options);
127
+ function defineFulgurjsPages(pages, options = {}) {
128
+ const violations = validateFulgurjsPages(pages, options);
129
129
  const errors = violations.filter((v) => v.level === "error");
130
130
  const warns = violations.filter((v) => v.level === "warn");
131
131
  const text = formatViolations(violations);
@@ -138,6 +138,6 @@ function defineFulgurPages(pages, options = {}) {
138
138
  return pages;
139
139
  }
140
140
  export {
141
- defineFulgurPages,
142
- validateFulgurPages
141
+ defineFulgurjsPages,
142
+ validateFulgurjsPages
143
143
  };
package/dist/runtime.js CHANGED
@@ -1,3 +1,3 @@
1
- var Q=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function k(t){let n=Q.exec(String(t).trim());return n?{major:Number(n[1]),minor:Number(n[2]??0),patch:Number(n[3]??0),pre:n[4]?n[4].split("."):[]}:null}function ee(t,n){if(t.length===0&&n.length===0)return 0;if(t.length===0)return 1;if(n.length===0)return-1;let o=Math.max(t.length,n.length);for(let r=0;r<o;r++){let l=t[r],m=n[r];if(l===void 0)return-1;if(m===void 0)return 1;let y=/^\d+$/.test(l),w=/^\d+$/.test(m);if(y&&w){let M=Number(l)-Number(m);if(M!==0)return M}else{if(y!==w)return y?-1:1;if(l!==m)return l<m?-1:1}}return 0}function T(t,n){let o=k(t),r=k(n);return!o||!r?t<n?-1:t>n?1:0:o.major!==r.major?o.major-r.major:o.minor!==r.minor?o.minor-r.minor:o.patch!==r.patch?o.patch-r.patch:ee(o.pre,r.pre)}var re=/^[a-z]+[+:-]/i;function N(t,n){if(n===!1||n==null||n==="")return!0;let o=String(n).trim();return!o||o==="*"||o==="latest"||re.test(o)?!0:o.split("||").some(r=>te(t,r.trim()))}function te(t,n){if(!n||n==="*")return!k(t)?.pre.length;let o=n.split(/\s+-\s+/);if(o.length===2){let m=o[0].trim(),y=o[1].trim();return!(!N(t,`>=${m}`)||!N(t,`<=${y}`))}let r=k(t);if(!r)return!1;let l=ne(n);if(l===null)return!0;for(let m of l)if(!ue(r,t,m))return!1;return!(r.pre.length>0&&!l.some(m=>m.ver.pre.length>0)&&!l.some(y=>y.ver.major===r.major&&y.ver.minor===r.minor&&y.ver.patch===r.patch))}function ne(t){let n=[],o=t.trim().split(/\s+/).filter(Boolean);if(o.length===0)return null;for(let r of o){let l=/^(>=|<=|>|<|=|\^|~)?(.*)$/.exec(r);if(!l)return null;let m=l[1],y=l[2],w=oe(m,y);if(w===null)return null;n.push(...w)}return n}function oe(t,n){let o=ae(n);if(!o)return null;let{ver:r,partial:l}=o;switch(t){case"^":{let m=ie(r);return m?[{op:">=",ver:r},{op:"<",ver:m}]:null}case"~":{let m=l>=2?{major:r.major,minor:r.minor+1,patch:0,pre:[]}:{major:r.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:r},{op:"<",ver:m}]}case">=":return[{op:">=",ver:r}];case">":return l===1?[{op:">=",ver:{major:r.major+1,minor:0,patch:0,pre:[]}}]:l===2?[{op:">=",ver:{major:r.major,minor:r.minor+1,patch:0,pre:[]}}]:[{op:">",ver:r}];case"<":return l===1?[{op:"<",ver:{major:r.major,minor:0,patch:0,pre:[]}}]:l===2?[{op:"<",ver:{major:r.major,minor:r.minor,patch:0,pre:[]}}]:[{op:"<",ver:r}];case"<=":return[{op:"<=",ver:r}];case"=":case void 0:return l===1?[{op:">=",ver:r},{op:"<",ver:{major:r.major+1,minor:0,patch:0,pre:[]}}]:l===2?[{op:">=",ver:r},{op:"<",ver:{major:r.major,minor:r.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:r}];default:return null}}function ie(t){return t.major>0?{major:t.major+1,minor:0,patch:0,pre:[]}:t.minor>0?{major:0,minor:t.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:t.patch+1,pre:[]}}function ae(t){let n=t.replace(/^v/,"").trim();if(!n||n==="*"||n==="x"||n==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let o=n.split("."),r=[],l=0;for(let w of o.slice(0,3))if(/^\d+$/.test(w))r.push(Number(w)),l++;else{if(w==="x"||w==="X"||w==="*")break;break}let m=n.split("-"),y=m.length>1?m.slice(1).join("-").split("+")[0].split("."):[];return l===0&&y.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:r[0]??0,minor:r[1]??0,patch:r[2]??0,pre:y},partial:l}}function se(t,n){switch(n){case">=":return t>=0;case">":return t>0;case"<":return t<0;case"<=":return t<=0;case"=":return t===0}}function ue(t,n,o){let r=`${t.major}.${t.minor}.${t.patch}`+(t.pre.length?`-${t.pre.join(".")}`:"");if(o.upper)return!(!(T(r,`${o.ver.major}.${o.ver.minor}.${o.ver.patch}`+(o.ver.pre.length?`-${o.ver.pre.join(".")}`:""))>=0)||!(T(r,`${o.upper.major}.${o.upper.minor}.${o.upper.patch}`)<0));let l=T(r,`${o.ver.major}.${o.ver.minor}.${o.ver.patch}`+(o.ver.pre.length?`-${o.ver.pre.join(".")}`:"")),m=se(l,o.op);return o.ver.pre.length>0&&t.pre.length===0&&(o.op===">"||o.op==="<")?!1:m}var g=class extends Error{code;details;constructor(n,o,r){super(`[fulgur:${n}] ${o}`),this.name="FulgurError",this.code=n,this.details=r}},R={REMOTE_LOAD_FAILED:"MFU-001",REMOTE_NAME_MISMATCH:"MFU-002",SHARE_STRICT_VERSION:"MFU-003",SHARE_NOT_AVAILABLE:"MFU-004",CONTAINER_REINIT_CONFLICT:"MFU-005",MODULE_NOT_EXPOSED:"MFU-006",PRELOAD_FAILED:"MFU-007",REMOTE_UNKNOWN:"MFU-008",EMPTY_EXPORTS:"MFU-009",SINGLETON_SKEW:"MFU-010"};var F="0.4.2";var U=15e3,P=2,ce=5,le=3e4;function fe(){let t={},n=new Map,o=[],r=new Map,l=new WeakMap,m={};function y(e){m={...m,...e},typeof globalThis<"u"&&(globalThis.__FULGUR_APP_CONFIG__=m)}function w(){return m}let M={},D=()=>{for(let e of o)try{e.init?.(M)}catch(i){console.warn("[fulgur] runtimePlugin init failed:",e.name,i)}},I=e=>t[e]??={};function $(e){try{M.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgur:error",{detail:e}))}function H(e="default"){return I(e),t}function K(e,i,a,u,E={}){let s=I(e||"default"),c=s[i]??={};c[a]||(c[a]={version:a,get:u,from:E.from??"unknown",eager:!!E.eager,loaded:!!E.loaded})}function x(e){for(let i of e){let a=n.get(i.name);n.set(i.name,{timeout:U,retries:P,...a,...i,state:a?.state??"idle",breakerState:a?.breakerState??{fails:0,openUntil:0},debug:a?.debug??{entry:i.entry,status:"idle"}})}}function q(e){x([e])}function G(e){o.push(...e),D()}async function z(e,i={}){let a=i.shareScope||"default",u=i.shareKey||e,s=I(a)[u]||{},c=Object.keys(s),d=i.requiredVersion,f=c.filter(p=>d===void 0||d===!1||N(p,d)),b;if(i.singleton&&c.length>0){let p=c.filter(h=>s[h].loaded);if(b=[...p.length?p:c].sort(T).pop(),c.length>1||!f.includes(b)){let h=s[b],O=`singleton skew "${u}": req "${d??"any"}" use ${b} from ${h.from}`;if(i.strictVersion){let v=new g(R.SHARE_STRICT_VERSION,O,{shareKey:u,requiredVersion:d});throw $({remote:h.from,error:v}),v}console.warn(`[fulgur:MFU-010] ${O}`)}}else if(b=[...f].sort(T).pop(),!b){if(i.strictVersion){let h=new g(R.SHARE_STRICT_VERSION,`no satisfying version for "${u}" (required "${d}") in share scope "${a}"`);throw $({remote:u,error:h}),h}if(i.fallback)return i.fallback();let p=new g(R.SHARE_NOT_AVAILABLE,`shared "${u}" (${d??"any"}) unavailable in scope "${a}" (no local fallback)`,{shareKey:u,requiredVersion:d});throw $({remote:u,error:p}),p}let _=s[b];if(M.resolveShare){let p=await M.resolveShare({shareKey:u,shareScope:a,requiredVersion:d,picked:_,available:Object.values(s)});p&&(_=p)}return _.loaded=!0,_.get()}function W(e,i,a){return new Promise((u,E)=>{let s=setTimeout(()=>E(new Error(`timeout after ${i}ms: ${a}`)),i);e.then(c=>{clearTimeout(s),u(c)},c=>{clearTimeout(s),E(c)})})}let B=e=>new Promise(i=>setTimeout(i,e));function j(e,i){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${i.name}" does not export a container interface (get/init)`);if(e.name&&i.name&&e.name!==i.name){let a=`remoteEntry self-reported name "${e.name}" mismatches configured name "${i.name}"`;if(i.promise)console.warn(`[fulgur] ${a} (promise-based remote, continuing)`);else throw Object.assign(new Error(a),{code:R.REMOTE_NAME_MISMATCH})}}async function L(e,i){return W(import(e),i.timeout??U,`load remoteEntry ${e}`)}async function C(e,i){let a=e.shareScope||"default";if(e.container){let s=l.get(e.container);if(s&&s!==a)throw new g(R.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${s}", cannot re-init with "${a}"`);return e.container}if(e.containerPromise)return e.containerPromise;let u=e.breakerState;if(u.openUntil>Date.now()){let s=new g(R.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(u.openUntil).toISOString()}`,{remote:e.name});throw $({remote:e.name,error:s}),s}e.state="loading",e.debug.status="loading";let E=(async()=>{let s=[];if(e.promise)s.push(async()=>{let p=await e.promise(),h=typeof p=="string"?await L(p,e):p;return j(h,e),h});else for(let p of[e.entry,...e.fallback??[]])s.push(async()=>{let h=await L(p,e);return j(h,e),h});let c,d,f=!1,b=i?.retries??e.retries??P;for(let p of s){for(let h=0;h<=b;h++){let O=performance.now();try{c=await p(),e.lastLoadMs=Math.round(performance.now()-O),e.debug.lastLoadMs=e.lastLoadMs,f=!0;break}catch(v){if(d=v,v?.code)throw v;h<b&&await B(200*2**h)}}if(f)break}if(!f||!c){let p=[];throw/^https?:\/\//.test(e.entry)&&typeof location<"u"?(p.push(`1. is the remote dev server running? try opening ${e.entry} in the browser \u2014 it must return JS, not HTML/an error`),p.push("2. is the URL correct in federation({ remotes })? dev and prod entries can differ"),p.push("3. CORS: the remote dev server must allow cross-origin requests (fulgur-federation enables server.cors automatically; a custom server config may have disabled it)")):(p.push(`1. is the remote deployed and reachable? try opening ${e.entry} in the browser \u2014 it must return JS`),p.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS file (check try_files / fallback rules)")),new g(R.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${e.entry}: ${String(d?.message??d)}
1
+ var Q=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function O(t){let n=Q.exec(String(t).trim());return n?{major:Number(n[1]),minor:Number(n[2]??0),patch:Number(n[3]??0),pre:n[4]?n[4].split("."):[]}:null}function ee(t,n){if(t.length===0&&n.length===0)return 0;if(t.length===0)return 1;if(n.length===0)return-1;let o=Math.max(t.length,n.length);for(let r=0;r<o;r++){let l=t[r],m=n[r];if(l===void 0)return-1;if(m===void 0)return 1;let y=/^\d+$/.test(l),w=/^\d+$/.test(m);if(y&&w){let $=Number(l)-Number(m);if($!==0)return $}else{if(y!==w)return y?-1:1;if(l!==m)return l<m?-1:1}}return 0}function v(t,n){let o=O(t),r=O(n);return!o||!r?t<n?-1:t>n?1:0:o.major!==r.major?o.major-r.major:o.minor!==r.minor?o.minor-r.minor:o.patch!==r.patch?o.patch-r.patch:ee(o.pre,r.pre)}var re=/^[a-z]+[+:-]/i;function k(t,n){if(n===!1||n==null||n==="")return!0;let o=String(n).trim();return!o||o==="*"||o==="latest"||re.test(o)?!0:o.split("||").some(r=>te(t,r.trim()))}function te(t,n){if(!n||n==="*")return!O(t)?.pre.length;let o=n.split(/\s+-\s+/);if(o.length===2){let m=o[0].trim(),y=o[1].trim();return!(!k(t,`>=${m}`)||!k(t,`<=${y}`))}let r=O(t);if(!r)return!1;let l=ne(n);if(l===null)return!0;for(let m of l)if(!ue(r,t,m))return!1;return!(r.pre.length>0&&!l.some(m=>m.ver.pre.length>0)&&!l.some(y=>y.ver.major===r.major&&y.ver.minor===r.minor&&y.ver.patch===r.patch))}function ne(t){let n=[],o=t.trim().split(/\s+/).filter(Boolean);if(o.length===0)return null;for(let r of o){let l=/^(>=|<=|>|<|=|\^|~)?(.*)$/.exec(r);if(!l)return null;let m=l[1],y=l[2],w=oe(m,y);if(w===null)return null;n.push(...w)}return n}function oe(t,n){let o=ae(n);if(!o)return null;let{ver:r,partial:l}=o;switch(t){case"^":{let m=ie(r);return m?[{op:">=",ver:r},{op:"<",ver:m}]:null}case"~":{let m=l>=2?{major:r.major,minor:r.minor+1,patch:0,pre:[]}:{major:r.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:r},{op:"<",ver:m}]}case">=":return[{op:">=",ver:r}];case">":return l===1?[{op:">=",ver:{major:r.major+1,minor:0,patch:0,pre:[]}}]:l===2?[{op:">=",ver:{major:r.major,minor:r.minor+1,patch:0,pre:[]}}]:[{op:">",ver:r}];case"<":return l===1?[{op:"<",ver:{major:r.major,minor:0,patch:0,pre:[]}}]:l===2?[{op:"<",ver:{major:r.major,minor:r.minor,patch:0,pre:[]}}]:[{op:"<",ver:r}];case"<=":return[{op:"<=",ver:r}];case"=":case void 0:return l===1?[{op:">=",ver:r},{op:"<",ver:{major:r.major+1,minor:0,patch:0,pre:[]}}]:l===2?[{op:">=",ver:r},{op:"<",ver:{major:r.major,minor:r.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:r}];default:return null}}function ie(t){return t.major>0?{major:t.major+1,minor:0,patch:0,pre:[]}:t.minor>0?{major:0,minor:t.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:t.patch+1,pre:[]}}function ae(t){let n=t.replace(/^v/,"").trim();if(!n||n==="*"||n==="x"||n==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let o=n.split("."),r=[],l=0;for(let w of o.slice(0,3))if(/^\d+$/.test(w))r.push(Number(w)),l++;else{if(w==="x"||w==="X"||w==="*")break;break}let m=n.split("-"),y=m.length>1?m.slice(1).join("-").split("+")[0].split("."):[];return l===0&&y.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:r[0]??0,minor:r[1]??0,patch:r[2]??0,pre:y},partial:l}}function se(t,n){switch(n){case">=":return t>=0;case">":return t>0;case"<":return t<0;case"<=":return t<=0;case"=":return t===0}}function ue(t,n,o){let r=`${t.major}.${t.minor}.${t.patch}`+(t.pre.length?`-${t.pre.join(".")}`:"");if(o.upper)return!(!(v(r,`${o.ver.major}.${o.ver.minor}.${o.ver.patch}`+(o.ver.pre.length?`-${o.ver.pre.join(".")}`:""))>=0)||!(v(r,`${o.upper.major}.${o.upper.minor}.${o.upper.patch}`)<0));let l=v(r,`${o.ver.major}.${o.ver.minor}.${o.ver.patch}`+(o.ver.pre.length?`-${o.ver.pre.join(".")}`:"")),m=se(l,o.op);return o.ver.pre.length>0&&t.pre.length===0&&(o.op===">"||o.op==="<")?!1:m}var g=class extends Error{code;details;constructor(n,o,r){super(`[fulgurjs:${n}] ${o}`),this.name="FulgurjsError",this.code=n,this.details=r}},R={REMOTE_LOAD_FAILED:"MFU-001",REMOTE_NAME_MISMATCH:"MFU-002",SHARE_STRICT_VERSION:"MFU-003",SHARE_NOT_AVAILABLE:"MFU-004",CONTAINER_REINIT_CONFLICT:"MFU-005",MODULE_NOT_EXPOSED:"MFU-006",PRELOAD_FAILED:"MFU-007",REMOTE_UNKNOWN:"MFU-008",EMPTY_EXPORTS:"MFU-009",SINGLETON_SKEW:"MFU-010"};var F="0.5.0";var U=15e3,P=2,ce=5,le=3e4;function fe(){let t={},n=new Map,o=[],r=new Map,l=new WeakMap,m={};function y(e){m={...m,...e},typeof globalThis<"u"&&(globalThis.__FULGURJS_APP_CONFIG__=m)}function w(){return m}let $={},D=()=>{for(let e of o)try{e.init?.($)}catch(i){console.warn("[fulgurjs] runtimePlugin init failed:",e.name,i)}},N=e=>t[e]??={};function j(e){try{$.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function H(e="default"){return N(e),t}function K(e,i,a,u,E={}){let s=N(e||"default"),c=s[i]??={};c[a]||(c[a]={version:a,get:u,from:E.from??"unknown",eager:!!E.eager,loaded:!!E.loaded})}function x(e){for(let i of e){let a=n.get(i.name);n.set(i.name,{timeout:U,retries:P,...a,...i,state:a?.state??"idle",breakerState:a?.breakerState??{fails:0,openUntil:0},debug:a?.debug??{entry:i.entry,status:"idle"}})}}function q(e){x([e])}function G(e){o.push(...e),D()}async function z(e,i={}){let a=i.shareScope||"default",u=i.shareKey||e,s=N(a)[u]||{},c=Object.keys(s),d=i.requiredVersion,f=c.filter(p=>d===void 0||d===!1||k(p,d)),b;if(i.singleton&&c.length>0){let p=c.filter(h=>s[h].loaded);if(b=[...p.length?p:c].sort(v).pop(),c.length>1||!f.includes(b)){let h=s[b],T=`singleton skew "${u}": req "${d??"any"}" use ${b} from ${h.from}`;if(i.strictVersion){let M=new g(R.SHARE_STRICT_VERSION,T,{shareKey:u,requiredVersion:d});throw j({remote:h.from,error:M}),M}console.warn(`[fulgurjs:MFU-010] ${T}`)}}else if(b=[...f].sort(v).pop(),!b){if(i.strictVersion){let h=new g(R.SHARE_STRICT_VERSION,`no satisfying version for "${u}" (required "${d}") in share scope "${a}"`);throw j({remote:u,error:h}),h}if(i.fallback)return i.fallback();let p=new g(R.SHARE_NOT_AVAILABLE,`shared "${u}" (${d??"any"}) unavailable in scope "${a}" (no local fallback)`,{shareKey:u,requiredVersion:d});throw j({remote:u,error:p}),p}let _=s[b];if($.resolveShare){let p=await $.resolveShare({shareKey:u,shareScope:a,requiredVersion:d,picked:_,available:Object.values(s)});p&&(_=p)}return _.loaded=!0,_.get()}function J(e,i,a){return new Promise((u,E)=>{let s=setTimeout(()=>E(new Error(`timeout after ${i}ms: ${a}`)),i);e.then(c=>{clearTimeout(s),u(c)},c=>{clearTimeout(s),E(c)})})}let W=e=>new Promise(i=>setTimeout(i,e));function I(e,i){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${i.name}" does not export a container interface (get/init)`);if(e.name&&i.name&&e.name!==i.name){let a=`remoteEntry self-reported name "${e.name}" mismatches configured name "${i.name}"`;if(i.promise)console.warn(`[fulgurjs] ${a} (promise-based remote, continuing)`);else throw Object.assign(new Error(a),{code:R.REMOTE_NAME_MISMATCH})}}async function L(e,i){return J(import(e),i.timeout??U,`load remoteEntry ${e}`)}async function C(e,i){let a=e.shareScope||"default";if(e.container){let s=l.get(e.container);if(s&&s!==a)throw new g(R.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${s}", cannot re-init with "${a}"`);return e.container}if(e.containerPromise)return e.containerPromise;let u=e.breakerState;if(u.openUntil>Date.now()){let s=new g(R.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(u.openUntil).toISOString()}`,{remote:e.name});throw j({remote:e.name,error:s}),s}e.state="loading",e.debug.status="loading";let E=(async()=>{let s=[];if(e.promise)s.push(async()=>{let p=await e.promise(),h=typeof p=="string"?await L(p,e):p;return I(h,e),h});else for(let p of[e.entry,...e.fallback??[]])s.push(async()=>{let h=await L(p,e);return I(h,e),h});let c,d,f=!1,b=i?.retries??e.retries??P;for(let p of s){for(let h=0;h<=b;h++){let T=performance.now();try{c=await p(),e.lastLoadMs=Math.round(performance.now()-T),e.debug.lastLoadMs=e.lastLoadMs,f=!0;break}catch(M){if(d=M,M?.code)throw M;h<b&&await W(200*2**h)}}if(f)break}if(!f||!c){let p=[];throw/^https?:\/\//.test(e.entry)&&typeof location<"u"?(p.push(`1. is the remote dev server running? try opening ${e.entry} in the browser \u2014 it must return JS, not HTML/an error`),p.push("2. is the URL correct in federation({ remotes })? dev and prod entries can differ"),p.push("3. CORS: the remote dev server must allow cross-origin requests (fulgurjs-federation enables server.cors automatically; a custom server config may have disabled it)")):(p.push(`1. is the remote deployed and reachable? try opening ${e.entry} in the browser \u2014 it must return JS`),p.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS file (check try_files / fallback rules)")),new g(R.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${e.entry}: ${String(d?.message??d)}
2
2
  `+p.join(`
3
- `),{remote:e.name})}j(c,e);let _=l.get(c);if(_&&_!==a)throw new g(R.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${_}", cannot re-init with "${a}"`);return typeof c.init=="function"&&await c.init(t),l.set(c,a),e.container=c,e.state="loaded",e.debug.status="loaded",u.fails=0,c})();e.containerPromise=E;try{return await E}catch(s){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(s?.message??s),u.fails+=1,u.fails>=ce&&(u.openUntil=Date.now()+le,u.fails=0),s instanceof g)throw $({remote:e.name,error:s}),s;if(s?.code)throw $({remote:e.name,error:s}),s;let c=new g(R.REMOTE_LOAD_FAILED,String(s?.message??s),{remote:e.name});throw $({remote:e.name,error:c}),c}}function A(e){let i=e.indexOf("/");return i===-1?{remote:e,module:""}:{remote:e.slice(0,i),module:X(e.slice(i+1))}}function X(e){return e?e.startsWith(".")?e:`./${e}`:""}async function J(e,i){let{remote:a,module:u}=A(e);M.beforeLoadRemote?.({remote:a,module:u});let E=n.get(a);if(!E)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${a}". Register it via federation({ remotes }) or registerRemote().`,{remote:a});let s;try{s=await C(E,{retries:i?.retries})}catch(f){if(i?.fallbackModule)return console.error(`[fulgur] loadRemote("${e}") failed; returning fallbackModule (\u663E\u5F0F\u964D\u7EA7\uFF0C\u9519\u8BEF\u5DF2\u900F\u51FA)`,f),$({remote:a,error:f}),await i.fallbackModule();throw f}if(!u)return s;let c=`${a}@${E.shareScope||"default"}#${u}`;r.has(c)||r.set(c,s.get(u).catch(f=>{throw r.delete(c),f instanceof g||f?.code?f:new g(R.REMOTE_LOAD_FAILED,`failed to load module "${u}" from remote "${a}": ${String(f?.message??f)}`,{remote:a,module:u})}));let d;try{d=await r.get(c)}catch(f){if(i?.fallbackModule)return console.error(`[fulgur] loadRemote("${e}") failed; returning fallbackModule (\u663E\u5F0F\u964D\u7EA7\uFF0C\u9519\u8BEF\u5DF2\u900F\u51FA)`,f),$({remote:a,error:f}),await i.fallbackModule();throw f}if(M.afterLoadRemote?.({remote:a,module:u,module_ns:d}),d&&typeof d=="object"&&Object.keys(d).length===0){let f=new g(R.EMPTY_EXPORTS,`no exports: ${u} @ ${a}`,{remote:a,module:u});$({remote:a,error:f}),console.error(`[fulgur:MFU-009] ${f.message}`)}return d}function Y(e){let i=n.get(e);if(!i)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return C(i)}async function Z(e,i={}){let{remote:a}=A(e),u=n.get(a);if(!u)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${a}"`,{remote:a});let E=i.mode??"preload",s=(c,d)=>{if(typeof document>"u"||document.querySelector(`link[href="${c}"]`))return;let f=document.createElement("link");f.rel=d==="style"?"stylesheet":"modulepreload",f.href=c,E==="prefetch"&&(f.fetchPriority="low"),document.head.appendChild(f)};try{if(u.manifestUrl){let c=await fetch(u.manifestUrl,{cache:"no-cache"});if(c.ok){let d=await c.json();s(u.entry,"modulepreload");let f=d.exposes??{};for(let b of Object.keys(f)){let _=f[b];_?.file&&s(new URL(_.file,u.entry).href,"modulepreload");for(let p of _?.css??[])s(new URL(p,u.entry).href,"style")}return}}s(u.entry,"modulepreload")}catch(c){$({remote:a,error:new g(R.PRELOAD_FAILED,String(c?.message??c),{remote:a})})}}return typeof window>"u"||(window.__FULGUR_SCOPE__=t,window.__FULGUR_INFO__={get remotes(){let e={};for(let[i,a]of n)e[i]={...a.debug,entry:a.entry};return e},errors:[]}),{shareScopeMap:t,initSharing:H,registerShare:K,registerRemotes:x,registerRemote:q,registerPlugins:G,loadShare:z,loadRemote:J,getContainer:Y,preloadRemote:Z,parseSpec:A,provideFulgurAppConfig:y,getFulgurAppConfig:w}}var V=globalThis,S=V.__FULGUR_RUNTIME__??fe();V.__FULGUR_RUNTIME__=S;try{Object.freeze(S)}catch{}var Re=F;function Se(){return S}var we=S.initSharing,be=S.registerShare,_e=S.registerRemotes,$e=S.registerRemote,Me=S.registerPlugins,ve=S.loadShare,Te=S.loadRemote,Oe=S.getContainer,ke=S.preloadRemote,Ne=S.shareScopeMap,Ie=S.provideFulgurAppConfig,je=S.getFulgurAppConfig;function Ae(t){if(t&&typeof t=="object"&&"default"in t){let n=t.default;return n!==void 0?n:t}return t}var xe=S;export{xe as default,Oe as getContainer,je as getFulgurAppConfig,Se as getRuntime,we as initSharing,Te as loadRemote,ve as loadShare,ke as preloadRemote,Ie as provideFulgurAppConfig,Me as registerPlugins,$e as registerRemote,_e as registerRemotes,be as registerShare,S as runtime,Ne as shareScopeMap,Ae as unwrapDefault,Re as version};
3
+ `),{remote:e.name})}I(c,e);let _=l.get(c);if(_&&_!==a)throw new g(R.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${_}", cannot re-init with "${a}"`);return typeof c.init=="function"&&await c.init(t),l.set(c,a),e.container=c,e.state="loaded",e.debug.status="loaded",u.fails=0,c})();e.containerPromise=E;try{return await E}catch(s){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(s?.message??s),u.fails+=1,u.fails>=ce&&(u.openUntil=Date.now()+le,u.fails=0),s instanceof g)throw j({remote:e.name,error:s}),s;if(s?.code)throw j({remote:e.name,error:s}),s;let c=new g(R.REMOTE_LOAD_FAILED,String(s?.message??s),{remote:e.name});throw j({remote:e.name,error:c}),c}}function A(e){let i=e.indexOf("/");return i===-1?{remote:e,module:""}:{remote:e.slice(0,i),module:B(e.slice(i+1))}}function B(e){return e?e.startsWith(".")?e:`./${e}`:""}async function X(e,i){let{remote:a,module:u}=A(e);$.beforeLoadRemote?.({remote:a,module:u});let E=n.get(a);if(!E)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${a}". Register it via federation({ remotes }) or registerRemote().`,{remote:a});let s;try{s=await C(E,{retries:i?.retries})}catch(f){if(i?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\u663E\u5F0F\u964D\u7EA7\uFF0C\u9519\u8BEF\u5DF2\u900F\u51FA)`,f),j({remote:a,error:f}),await i.fallbackModule();throw f}if(!u)return s;let c=`${a}@${E.shareScope||"default"}#${u}`;r.has(c)||r.set(c,s.get(u).catch(f=>{throw r.delete(c),f instanceof g||f?.code?f:new g(R.REMOTE_LOAD_FAILED,`failed to load module "${u}" from remote "${a}": ${String(f?.message??f)}`,{remote:a,module:u})}));let d;try{d=await r.get(c)}catch(f){if(i?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\u663E\u5F0F\u964D\u7EA7\uFF0C\u9519\u8BEF\u5DF2\u900F\u51FA)`,f),j({remote:a,error:f}),await i.fallbackModule();throw f}if($.afterLoadRemote?.({remote:a,module:u,module_ns:d}),d&&typeof d=="object"&&Object.keys(d).length===0){let f=new g(R.EMPTY_EXPORTS,`no exports: ${u} @ ${a}`,{remote:a,module:u});j({remote:a,error:f}),console.error(`[fulgurjs:MFU-009] ${f.message}`)}return d}function Y(e){let i=n.get(e);if(!i)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return C(i)}async function Z(e,i={}){let{remote:a}=A(e),u=n.get(a);if(!u)throw new g(R.REMOTE_UNKNOWN,`unknown remote "${a}"`,{remote:a});let E=i.mode??"preload",s=(c,d)=>{if(typeof document>"u"||document.querySelector(`link[href="${c}"]`))return;let f=document.createElement("link");f.rel=d==="style"?"stylesheet":"modulepreload",f.href=c,E==="prefetch"&&(f.fetchPriority="low"),document.head.appendChild(f)};try{if(u.manifestUrl){let c=await fetch(u.manifestUrl,{cache:"no-cache"});if(c.ok){let d=await c.json();s(u.entry,"modulepreload");let f=d.exposes??{};for(let b of Object.keys(f)){let _=f[b];_?.file&&s(new URL(_.file,u.entry).href,"modulepreload");for(let p of _?.css??[])s(new URL(p,u.entry).href,"style")}return}}s(u.entry,"modulepreload")}catch(c){j({remote:a,error:new g(R.PRELOAD_FAILED,String(c?.message??c),{remote:a})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=t,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[i,a]of n)e[i]={...a.debug,entry:a.entry};return e},errors:[]}),{shareScopeMap:t,initSharing:H,registerShare:K,registerRemotes:x,registerRemote:q,registerPlugins:G,loadShare:z,loadRemote:X,getContainer:Y,preloadRemote:Z,parseSpec:A,provideFulgurjsAppConfig:y,getFulgurjsAppConfig:w}}var V=globalThis,S=V.__FULGURJS_RUNTIME__??fe();V.__FULGURJS_RUNTIME__=S;try{Object.freeze(S)}catch{}var Re=F;function Se(){return S}var we=S.initSharing,be=S.registerShare,_e=S.registerRemotes,je=S.registerRemote,$e=S.registerPlugins,Me=S.loadShare,ve=S.loadRemote,Te=S.getContainer,Oe=S.preloadRemote,ke=S.shareScopeMap,Ne=S.provideFulgurjsAppConfig,Ie=S.getFulgurjsAppConfig;function Ae(t){if(t&&typeof t=="object"&&"default"in t){let n=t.default;return n!==void 0?n:t}return t}var xe=S;export{xe as default,Te as getContainer,Ie as getFulgurjsAppConfig,Se as getRuntime,we as initSharing,ve as loadRemote,Me as loadShare,Oe as preloadRemote,Ne as provideFulgurjsAppConfig,$e as registerPlugins,je as registerRemote,_e as registerRemotes,be as registerShare,S as runtime,ke as shareScopeMap,Ae as unwrapDefault,Re as version};
package/docs/manual.html CHANGED
@@ -55,12 +55,12 @@
55
55
  <h2 id="compare">1. 与 Webpack 原版对齐总表</h2>
56
56
  <p>结论先行:<b>在 Vite↔Vite 场景下,配置面与运行时行为 100% 对齐 webpack ModuleFederationPlugin</b>;
57
57
  唯二例外为 <code>remoteType: 'script'/'var'</code>(跨打包器互操作,P3 里程碑)与 Chrome DevTools 扩展(用
58
- <code>window.__FULGUR_SCOPE__</code> 调试出口替代)。</p>
58
+ <code>window.__FULGURJS_SCOPE__</code> 调试出口替代)。</p>
59
59
 
60
60
  <h3>1.1 配置面(webpack 官方全选项)</h3>
61
61
  <table>
62
- <tr><th>webpack 选项</th><th>fulgur</th><th>说明</th></tr>
63
- <tr><td><code>name</code> / <code>filename</code></td><td class="ok">✅ 一致</td><td>容器名 + remoteEntry 稳定文件名(默认 <code>fulgur-remoteEntry.js</code>)</td></tr>
62
+ <tr><th>webpack 选项</th><th>fulgurjs</th><th>说明</th></tr>
63
+ <tr><td><code>name</code> / <code>filename</code></td><td class="ok">✅ 一致</td><td>容器名 + remoteEntry 稳定文件名(默认 <code>fulgurjs-remoteEntry.js</code>)</td></tr>
64
64
  <tr><td><code>exposes</code> 字符串 / 对象 <code>{import, name}</code></td><td class="ok">✅ 一致</td><td>对象形式 name = 稳定 chunk 名</td></tr>
65
65
  <tr><td><code>remotes</code> 的 <code>name@url</code> 语法</td><td class="ok">✅ 一致</td><td>@ 前自报名校验;键重命名(checkout: shop@…)</td></tr>
66
66
  <tr><td><code>remotes</code> 对象 <code>{external, shareScope}</code></td><td class="ok">✅ 一致</td><td>另支持 <code>dev</code>/<code>prod</code> 地址拆分(webpack 没有的增强)</td></tr>
@@ -71,17 +71,17 @@
71
71
  <tr><td><code>shareScope</code> 多作用域</td><td class="ok">✅ 一致</td><td>命名空间互相隔离</td></tr>
72
72
  <tr><td><code>eager</code></td><td class="ok">✅ 一致</td><td>初始 chunk 可用 + 总被下载</td></tr>
73
73
  <tr><td><code>runtime</code> / <code>runtimeChunk</code></td><td class="ok">✅ 一致</td><td>运行时与 init 独立产物、稳定命名</td></tr>
74
- <tr><td><code>manifest</code></td><td class="ok">✅</td><td>fulgur-manifest.json(部署回滚 = 切 manifest 指针)</td></tr>
74
+ <tr><td><code>manifest</code></td><td class="ok">✅</td><td>fulgurjs-manifest.json(部署回滚 = 切 manifest 指针)</td></tr>
75
75
  <tr><td><code>runtimePlugins</code></td><td class="ok">✅</td><td>resolveShare / beforeLoadRemote / afterLoadRemote / onRemoteError 钩子</td></tr>
76
76
  <tr><td><code>dts</code></td><td class="ok">✅</td><td>dev 源码级类型直连</td></tr>
77
77
  <tr><td><code>automaticAsyncBoundary</code> / <code>dataPrefetch</code> / <code>usedExports</code></td><td class="warn">🔶 增强</td><td>TLA 自动异步边界(无需手工 bootstrap)、preloadRemote 常驻、Rollup 原生 tree-shaking</td></tr>
78
78
  <tr><td><code>remoteType: 'script'/'var'</code></td><td class="warn">🔶 P3</td><td>跨打包器互操作(webpack 宿主消费 Vite remote),首发不承诺</td></tr>
79
- <tr><td>Chrome DevTools 扩展</td><td class="warn">🔶 替代</td><td><code>window.__FULGUR_SCOPE__ / __FULGUR_INFO__</code> 调试出口</td></tr>
79
+ <tr><td>Chrome DevTools 扩展</td><td class="warn">🔶 替代</td><td><code>window.__FULGURJS_SCOPE__ / __FULGURJS_INFO__</code> 调试出口</td></tr>
80
80
  </table>
81
81
 
82
82
  <h3>1.2 运行时行为语义(18 条逐条 e2e 验收)</h3>
83
83
  <table>
84
- <tr><th>#</th><th>webpack 行为</th><th>fulgur</th></tr>
84
+ <tr><th>#</th><th>webpack 行为</th><th>fulgurjs</th></tr>
85
85
  <tr><td>1</td><td>协商取满足 requiredVersion 的<b>最高版本</b></td><td class="ok">✅</td></tr>
86
86
  <tr><td>2</td><td>非 singleton 多版本共存</td><td class="ok">✅</td></tr>
87
87
  <tr><td>3</td><td>已注册/已加载版本永不替换(first-wins)</td><td class="ok">✅</td></tr>
@@ -117,7 +117,7 @@ export default defineConfig({
117
117
  vue(),
118
118
  federation({
119
119
  name: 'remote-a',
120
- filename: 'fulgur-remoteEntry.js',
120
+ filename: 'fulgurjs-remoteEntry.js',
121
121
  exposes: {
122
122
  './Button': './src/exposes/Button.vue',
123
123
  './utils': './src/exposes/utils.ts',
@@ -134,7 +134,7 @@ export default defineConfig({
134
134
  <pre>federation({
135
135
  name: 'host-app',
136
136
  remotes: {
137
- // 单地址:dev 自动拼 @fulgur-entry.js,prod 自动拼 remoteEntry 文件名
137
+ // 单地址:dev 自动拼 @fulgurjs-entry.js,prod 自动拼 remoteEntry 文件名
138
138
  'remote-a': 'http://localhost:5101',
139
139
  // 显式拆分(推荐用于部署)
140
140
  'remote-b': { dev: 'http://localhost:5102', prod: 'https://cdn.example.com/remote-b/' },
@@ -159,18 +159,18 @@ import Btn from 'remote-a/Button'</pre>
159
159
  <table>
160
160
  <tr><th>环境</th><th>引擎</th><th>机制</th></tr>
161
161
  <tr><td><b>dev</b></td><td>双 dev-server 协作</td>
162
- <td>remote 的 dev server 暴露 <code>/@fulgur-entry.js</code>(自包含容器)与 <code>/@fulgur-manifest.json</code>;
162
+ <td>remote 的 dev server 暴露 <code>/@fulgurjs-entry.js</code>(自包含容器)与 <code>/@fulgurjs-manifest.json</code>;
163
163
  宿主页面经运行时 <code>container.init(shareScopeMap)</code> 收养共享作用域;remote 模块的 shared 导入经
164
164
  <b>绑定门面</b>(按需生成的虚拟模块)协商到宿主实例;HMR 通过 remote 的 vite client 直连宿主页面。</td></tr>
165
165
  <tr><td><b>prod</b></td><td>构建期改写(Rollup/Rolldown)</td>
166
166
  <td>每个 expose 生成虚拟入口 → 独立 chunk;shared 经动态导入边界自动剥离;产出稳定文件名的
167
- <code>fulgur-remoteEntry.js</code> + <code>fulgur-manifest.json</code>;宿主入口前置 init import 注册 remotes/provides。</td></tr>
167
+ <code>fulgurjs-remoteEntry.js</code> + <code>fulgurjs-manifest.json</code>;宿主入口前置 init import 注册 remotes/provides。</td></tr>
168
168
  </table>
169
169
  <div class="note">运行时内核 gzip 约 <b>5.0KB</b>(对标 @module-federation/runtime 的 40KB+),页面级单例:
170
- 多应用各自打包的运行时副本经 <code>globalThis.__FULGUR_RUNTIME__</code> 合一。
170
+ 多应用各自打包的运行时副本经 <code>globalThis.__FULGURJS_RUNTIME__</code> 合一。
171
171
  跨源取运行时的官方入口:<code>getRuntime()</code>(独立产物导出,与全局单例同一实例),
172
172
  单例带 <code>version</code> 字段(与插件包版本同源)用于副本一致性诊断;方法面已冻结防意外覆写。
173
- 注意:exposes 目标文件(远程页面)禁止静态导入 <code>virtual:fulgur-runtime</code>,插件 dev 下会显式报错(见 §8)。</div>
173
+ 注意:exposes 目标文件(远程页面)禁止静态导入 <code>virtual:fulgurjs-runtime</code>,插件 dev 下会显式报错(见 §8)。</div>
174
174
 
175
175
  <h2 id="feat">4. 功能章节(含实测截图)</h2>
176
176
 
@@ -196,7 +196,7 @@ import Btn from 'remote-a/Button'</pre>
196
196
  </div>
197
197
 
198
198
  <h3>4.4 Share Scope 协商可视化(调试出口)</h3>
199
- <p>宿主任意页面可用 <code>window.__FULGUR_SCOPE__</code> / <code>__FULGUR_INFO__</code> 查看协商结果与加载状态。</p>
199
+ <p>宿主任意页面可用 <code>window.__FULGURJS_SCOPE__</code> / <code>__FULGURJS_INFO__</code> 查看协商结果与加载状态。</p>
200
200
  <img class="shot" src="screenshots/dev-scope-debug-panel.png">
201
201
 
202
202
  <h3>4.5 remotes 键重命名(checkout: shop@ 语法)</h3>
@@ -240,7 +240,7 @@ const mod = await import('promise-remote/Button')</pre>
240
240
 
241
241
  <h3>4.12 dts 类型直连(dev 源码级补全)</h3>
242
242
  <p>宿主 dev server 启动时自动拉取各远程的 dev manifest,为每个 exposes 生成 <code>declare module</code> 声明,
243
- 映射到远程本机源码——补全与跳转都是源码级。产物写入 <code>src/fulgur-types/&lt;remote&gt;.d.ts</code>,
243
+ 映射到远程本机源码——补全与跳转都是源码级。产物写入 <code>src/fulgurjs-types/&lt;remote&gt;.d.ts</code>,
244
244
  确保 tsconfig include 包含该目录即可。</p>
245
245
  <pre>declare module 'remote-a/Button' {
246
246
  import type { DefineComponent } from 'vue'
@@ -252,7 +252,7 @@ const mod = await import('promise-remote/Button')</pre>
252
252
  <figcaption>实测:host-vue 启动后自动生成 remote-a / remote-b / shop 三份类型声明(5 + 2 + 5 个 exposes)</figcaption>
253
253
 
254
254
  <h3>4.13 preloadRemote(manifest 驱动精确预载)</h3>
255
- <pre>import { preloadRemote } from 'virtual:fulgur-runtime' // 插件已全局注入
255
+ <pre>import { preloadRemote } from 'virtual:fulgurjs-runtime' // 插件已全局注入
256
256
  await preloadRemote('remote-a') // 按 manifest 精确预载全部 exposes chunk + CSS
257
257
  await preloadRemote('remote-a', { mode: 'prefetch' }) // 低优先级预取</pre>
258
258
  <p>实测注入的 modulepreload 链接(dev):容器入口 + 全部 5 个 exposes 的源模块——
@@ -262,7 +262,7 @@ await preloadRemote('remote-a', { mode: 'prefetch' }) // 低优先级预取</pre
262
262
  <h2 id="tb">5. 示例工程 真实项目实战(qiankun 仓库 + 模块联邦平行通道)</h2>
263
263
  <p>复制 示例工程(三应用 monorepo) 到插件 testbed,保持 <b>qiankun 集成零改动</b>,新增联邦平行通道:
264
264
  示例宿主应用(Vite 6.4.3)作为宿主,示例 bpm 子应用(Vite 5.1.4,/flowable)与 示例 lowcode 子应用(Vite 5.2.12,/lowcode)
265
- 作为远程。免登录演示路由 <code>/main/fulgur-demo</code>(meta.ignoreAuth)。</p>
265
+ 作为远程。免登录演示路由 <code>/main/fulgurjs-demo</code>(meta.ignoreAuth)。</p>
266
266
  <pre>// admin remotes(dev/prod 自动切换,prod 走 NGINX 同源路径)
267
267
  'bpm-app': { dev: 'http://localhost:5102/bpm', prod: '/bpm' },
268
268
  'lowcode-app': { dev: 'http://localhost:5103/lowcode', prod: '/lowcode' },
@@ -276,13 +276,13 @@ const TaskCard = defineAsyncComponent(() =&gt; import('mes-bpm/TaskCard').then(m
276
276
  <img class="shot" src="screenshots/tb-dev-scope-negotiation.png">
277
277
 
278
278
  <h3>5.1 生产环境(NGINX 8662):真实远程产物 + 最小宿主</h3>
279
- <p>bpm/lowcode 生产构建产物(fulgur-remoteEntry.js + fulgur-manifest.json)部署到 NGINX 8662,
279
+ <p>bpm/lowcode 生产构建产物(fulgurjs-remoteEntry.js + fulgurjs-manifest.json)部署到 NGINX 8662,
280
280
  最小宿主页用<b>纯运行时容器 API</b>(无构建步骤)直接消费真实产物:</p>
281
- <pre>import { initSharing, registerRemotes, loadRemote, loadShare } from '/fulgur-runtime.js'
281
+ <pre>import { initSharing, registerRemotes, loadRemote, loadShare } from '/fulgurjs-runtime.js'
282
282
  initSharing('default')
283
283
  registerRemotes([
284
- { name: 'mes-bpm', entry: '/flowable/fulgur-remoteEntry.js' },
285
- { name: 'mes-lowcode', entry: '/lowcode/fulgur-remoteEntry.js' },
284
+ { name: 'mes-bpm', entry: '/flowable/fulgurjs-remoteEntry.js' },
285
+ { name: 'mes-lowcode', entry: '/lowcode/fulgurjs-remoteEntry.js' },
286
286
  ])
287
287
  const TaskCard = (await loadRemote('mes-bpm/./TaskCard')).default
288
288
  const vueMod = await loadShare('vue', { requiredVersion: '^3.4.0', singleton: true })</pre>
@@ -409,11 +409,11 @@ const vueMod = await loadShare('vue', { requiredVersion: '^3.4.0', singleton: tr
409
409
  <td>remote 未启动或端口错位(server.origin 同款),核对 VITE_PORT 与 remotes[].dev</td></tr>
410
410
  <tr><td><code>DEV-006</code></td><td>宿主/远程插件版本不一致</td>
411
411
  <td>统一各应用 @fulgurjs/federation 版本并重启 dev server</td></tr>
412
- <tr><td><code>DEV-008</code></td><td>exposes 目标文件(远程页面)静态导入 virtual:fulgur-runtime——宿主跨源加载时
412
+ <tr><td><code>DEV-008</code></td><td>exposes 目标文件(远程页面)静态导入 virtual:fulgurjs-runtime——宿主跨源加载时
413
413
  在远程模块图内求值第二份副本链,破坏渲染上下文。<strong>0.4.1 起插件自动把该导入改写为惰性单例委托
414
414
  (求值期零副作用、调用期转发页面级单例),不再报错</strong>;本码保留用于历史排查与极端场景说明</td>
415
- <td>无需任何处理——任何文件直接 <code>import { loadRemote } from 'virtual:fulgur-runtime'</code> 即可;
416
- 调试时可绕过代理直取 <code>(globalThis as any).__FULGUR_RUNTIME__</code></td></tr>
415
+ <td>无需任何处理——任何文件直接 <code>import { loadRemote } from 'virtual:fulgurjs-runtime'</code> 即可;
416
+ 调试时可绕过代理直取 <code>(globalThis as any).__FULGURJS_RUNTIME__</code></td></tr>
417
417
  <tr><td><code>DEV-009</code></td><td>联邦虚拟模块/门面请求 404(.vite 缓存漂移)——<strong>0.4.1 起插件在 dev server
418
418
  启动时自动检测插件版本变化并清除 .vite 缓存</strong></td>
419
419
  <td>重启 dev server 即可(缓存自清);若自动清理失败按提示手工 <code>rm -rf node_modules/.vite</code>;
@@ -24,7 +24,7 @@
24
24
  |------|------|------|
25
25
  | SSR | ❌ | 仅警告并禁用钩子;无 SSR 渲染计划 |
26
26
  | React/其他框架适配 | ❌ | 首发仅 Vue 3(shared 门面按 Vue 3 语义生成) |
27
- | 浏览器 DevTools 扩展 | ❌ | 提供 `window.__FULGUR_SCOPE__ / __FULGUR_INFO__` 调试面 |
27
+ | 浏览器 DevTools 扩展 | ❌ | 提供 `window.__FULGURJS_SCOPE__ / __FULGURJS_INFO__` 调试面 |
28
28
  | share 的 `import: false`(仅提供不消费) | ✅ import:false 已支持 | 与 webpack `eager`/share 语义对齐 |
29
29
  | 运行时动态 remote 版本浮动(promise remote 的 shared 注入) | ⚠️ | promise remote 可注册,但其 shared 需自带 |
30
30
  | Node.js 环境(SSR/构建外运行时) | ❌ | 仅浏览器 |
@@ -15,7 +15,7 @@
15
15
  - `__VUE_I18N_*`/`__INTLIFY_*` 5 个:vue-i18n 的编译期 feature flags(库本身行为)
16
16
  - `Prism`/`Sortable`:lowcode 设计器引入的第三方库全局
17
17
  - `exports`/`fs`/`stream`/`util`/`chokidar` 等:lowcode 某设计器依赖把 Node 风格 CJS 包装漏到 window(**原版乾坤下同样存在**,属子应用依赖自身的脏行为,与联邦无关)
18
- - 联邦运行时唯一注册面:`window.__FULGUR_SCOPE__`(值 `['default']`)与 `__FULGUR_INFO__`——无全局散落
18
+ - 联邦运行时唯一注册面:`window.__FULGURJS_SCOPE__`(值 `['default']`)与 `__FULGURJS_INFO__`——无全局散落
19
19
  - **未发现子应用覆盖宿主关键全局**
20
20
 
21
21
  ### 2. CSS
@@ -7,21 +7,21 @@
7
7
  | qiankun | @fulgurjs/federation |
8
8
  |---------|--------------------|
9
9
  | 主应用 registerMicroApps | 宿主 `federation({ remotes })` |
10
- | 子应用 entry(HTML) | remote entry(dev: `@fulgur-entry.js` 中间件 / prod: `fulgur-remoteEntry.js`) |
10
+ | 子应用 entry(HTML) | remote entry(dev: `@fulgurjs-entry.js` 中间件 / prod: `fulgurjs-remoteEntry.js`) |
11
11
  | 子应用生命周期 mount/unmount | 页面级 exposes(组件即入口,无生命周期样板) |
12
12
  | 主子应用 window 隔离/沙箱 | 无沙箱:同 realm 直渲染(`window.xxx` 全局桥自然可用) |
13
13
  | props 传递(qiankun 传参) | 组件 props(路由通道 = params+query 合并;弹窗通道 = 显式 v-bind) |
14
14
  | 公共依赖 externals/主应用共享 | `shared`(singleton 协商,"已加载优先") |
15
- | `qiankun` 运行时 + single-spa | `virtual:fulgur-runtime`(15KB 级,无 single-spa) |
15
+ | `qiankun` 运行时 + single-spa | `virtual:fulgurjs-runtime`(15KB 级,无 single-spa) |
16
16
 
17
17
  ## 二、迁移步骤(真实案例顺序)
18
18
 
19
19
  1. **子应用装插件 + exposes**:把原菜单路由表逐页映射为 `exposes`(`./pages/bpm/task/todo` 对应路由 `bpm/task/todo`)。
20
20
  2. **shared 声明**:vue/pinia/vue-router 设 singleton;**不要**把业务库(element-plus/avue/dayjs 等)放 shared——插件会在预构建与构建期自动处理其内部对 shared 键的引用(UMD/CJS-only 依赖支持)。
21
- 3. **宿主装插件 + remotes**:菜单 URL 通道由 `resolveFulgurPageFromPath` 按路由表解析 spec(见 `admin/src/qiankun/fulgurPages.ts`)。
21
+ 3. **宿主装插件 + remotes**:菜单 URL 通道由 `resolveFulgurjsPageFromPath` 按路由表解析 spec(见 `admin/src/qiankun/fulgurjsPages.ts`)。
22
22
  4. **全局环境迁移**:子应用依赖宿主的全局(用户/字典 store、i18n、全局组件)→ 写 `federatedBoot.ts` expose,宿主加载页面前 `bootRemoteOnce` 执行;失败必须显式报错(H3)。
23
23
  5. **路由参数**:页面组件用 `defineProps` 声明参数(id/taskId 等);宿主路由通道把 params+query 作为 props 传入。
24
- 6. **跨应用弹窗**:原 iframe 嵌子应用页 → `fulgurPageComponent(spec)` 直渲染 + props(见 FormDetailsModal);真外链(数据驱动 URL、AMIS 站点)保留 iframe。
24
+ 6. **跨应用弹窗**:原 iframe 嵌子应用页 → `fulgurjsPageComponent(spec)` 直渲染 + props(见 FormDetailsModal);真外链(数据驱动 URL、AMIS 站点)保留 iframe。
25
25
  7. **公共依赖坑**:
26
26
  - 子应用 axios 的响应解包形状要和后端一致(jeecg `{success,result}` vs yudao `{code,data}`)
27
27
  - 子应用全局注册(指令/组件)失败必须显式报错,禁止"忽略继续"
@@ -49,11 +49,11 @@
49
49
  | 7 | 登录异步链未完成就断言 | e2e 偶发被弹回登录页 | 等「登录表单消失」而非固定秒数;后台慢链 ≥15s |
50
50
  | 8 | 多版本组件库 CSS | 后加载覆盖 `:root` 变量 | 主流版本变量一致则无感;升级时留意 |
51
51
  | 9 | 后端缺端点 | 404/401 资源报错 | 代理/NGINX 层加诚实空响应垫片(不伪造业务数据) |
52
- | 10 | 远程页面(exposes 目标文件)静态导入 `virtual:fulgur-runtime` | 宿主跨源加载后渲染上下文破坏:resolveComponent / withDirectives / "Missing ref owner" 告警、内容区静默空白 | 改走宿主单例(见下节);插件 dev 下已对此显式报错拦截 |
52
+ | 10 | 远程页面(exposes 目标文件)静态导入 `virtual:fulgurjs-runtime` | 宿主跨源加载后渲染上下文破坏:resolveComponent / withDirectives / "Missing ref owner" 告警、内容区静默空白 | 改走宿主单例(见下节);插件 dev 下已对此显式报错拦截 |
53
53
 
54
54
  ### 三B-1、远程页面如何取宿主运行时(跨源单例契约)
55
55
 
56
- exposes 目标文件(被宿主跨源加载的远程页面/组件)**禁止静态 `import 'virtual:fulgur-runtime'`**——
56
+ exposes 目标文件(被宿主跨源加载的远程页面/组件)**禁止静态 `import 'virtual:fulgurjs-runtime'`**——
57
57
  该导入会改由远程 dev server 求值,在远程模块图内实例化第二份运行时副本,破坏渲染上下文
58
58
  (插件 dev 下已对此显式报错,错误信息即指向本节)。
59
59
 
@@ -61,11 +61,11 @@ exposes 目标文件(被宿主跨源加载的远程页面/组件)**禁止静
61
61
 
62
62
  ```ts
63
63
  // ① 直接读全局单例(bpm detail 页先例)
64
- const runtime = (globalThis as any).__FULGUR_RUNTIME__
64
+ const runtime = (globalThis as any).__FULGURJS_RUNTIME__
65
65
  const mod = await runtime.loadRemote('host-app/UserProfile')
66
66
 
67
67
  // ② 经独立产物 getRuntime()(最小宿主/无构建场景,见 manual §5.1)
68
- import { getRuntime, version } from '/fulgur-runtime.js'
68
+ import { getRuntime, version } from '/fulgurjs-runtime.js'
69
69
  const mod = await getRuntime().loadRemote('mes-bpm/./TaskCard')
70
70
  ```
71
71
 
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * 通用起步样例:一个宿主 + 一个远程(应用名/路径均为虚构)。
3
- * 用法:npx fulgur init --config examples/fulgur.config.example.ts
4
- * 完整字段说明见 `fulgur init` 生成的起步模板(fulgur init --template fulgur.config.ts)。
3
+ * 用法:npx fulgurjs init --config examples/fulgurjs.config.example.ts
4
+ * 完整字段说明见 `fulgurjs init` 生成的起步模板(fulgurjs init --template fulgurjs.config.ts)。
5
5
  */
6
- import { defineFulgurConfig } from '@fulgurjs/federation/config'
6
+ import { defineFulgurjsConfig } from '@fulgurjs/federation/config'
7
7
 
8
- export default defineFulgurConfig({
8
+ export default defineFulgurjsConfig({
9
9
  root: process.cwd(),
10
10
  apps: [
11
11
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fulgurjs/federation",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Vite Module Federation with full Webpack MF parity. Dev & production, no compromise.",
6
6
  "license": "MIT",
@@ -65,13 +65,13 @@
65
65
  },
66
66
  "repository": {
67
67
  "type": "git",
68
- "url": "git+https://github.com/chenmingye/fulgur-federation.git",
68
+ "url": "git+https://github.com/chenmingye/fulgurjs-federation.git",
69
69
  "directory": "packages/plugin"
70
70
  },
71
- "homepage": "https://github.com/chenmingye/fulgur-federation#readme",
71
+ "homepage": "https://github.com/chenmingye/fulgurjs-federation#readme",
72
72
  "author": "chenmingye (Jason)",
73
73
  "bugs": {
74
- "url": "https://github.com/chenmingye/fulgur-federation/issues"
74
+ "url": "https://github.com/chenmingye/fulgurjs-federation/issues"
75
75
  },
76
76
  "keywords": [
77
77
  "vite",
@@ -85,6 +85,6 @@
85
85
  "node": ">=18"
86
86
  },
87
87
  "bin": {
88
- "fulgur": "./dist/cli.js"
88
+ "fulgurjs": "./dist/cli.js"
89
89
  }
90
90
  }