@fulgurjs/federation 3.0.0 → 4.0.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/CHANGELOG.md +25 -0
- package/README.md +27 -25
- package/dist/chunk-AYS56IRF.js +42 -0
- package/dist/{chunk-YBS2PO34.js → chunk-X4LZDAZQ.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +85 -43
- package/dist/index.js +85 -43
- package/dist/runtime-entry.d.ts +279 -0
- package/dist/runtime-entry.js +5 -0
- package/dist/runtime.js +2 -2
- package/dist/vue-adapter.cjs +66 -0
- package/dist/vue-adapter.d.cts +16 -0
- package/dist/vue-adapter.d.ts +16 -0
- package/dist/vue-adapter.js +6 -0
- package/dist/vue.cjs +17 -18
- package/dist/vue.d.cts +4 -33
- package/dist/vue.d.ts +4 -33
- package/dist/vue.js +3 -845
- package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +12 -10
- package/package.json +13 -5
- package/client.d.ts +0 -180
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RUNTIME_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-X4LZDAZQ.js";
|
|
4
4
|
|
|
5
5
|
// src/index.ts
|
|
6
6
|
import path6 from "path";
|
|
@@ -768,8 +768,7 @@ function genRuntimeProxyModule() {
|
|
|
768
768
|
"registerRemotes",
|
|
769
769
|
"registerShare",
|
|
770
770
|
"initSharing",
|
|
771
|
-
"registerPlugins"
|
|
772
|
-
"parseSpec"
|
|
771
|
+
"registerPlugins"
|
|
773
772
|
];
|
|
774
773
|
const lines = [
|
|
775
774
|
`let __fulgurjs_mod_p;`,
|
|
@@ -778,6 +777,10 @@ function genRuntimeProxyModule() {
|
|
|
778
777
|
` return await __fulgurjs_mod_p;`,
|
|
779
778
|
`};`,
|
|
780
779
|
...promiseApis.map((m) => `export const ${m} = (...a) => __fulgurjs_rt().then((m2) => m2.${m}(...a));`),
|
|
780
|
+
// parseSpec 是同步纯函数:promise 转发会把返回值变成 Promise(返回对象上的属性
|
|
781
|
+
// 全部 undefined,3.0.0 门面切换时实测)——同步直读页面级单例(调用期单例必已由
|
|
782
|
+
// init 建立,时序契约同 shareScopeMap)
|
|
783
|
+
`export const parseSpec = (...a) => (globalThis).__FULGURJS_RUNTIME__.parseSpec(...a);`,
|
|
781
784
|
// shareScopeMap:本模块只会在应用代码 import 链里被求值——页面运行期单例必已由 init 建立
|
|
782
785
|
// (时序契约:宿主/远程 init 先于一切联邦模块),故求值期直读 globalThis 安全
|
|
783
786
|
`export const shareScopeMap = (globalThis).__FULGURJS_RUNTIME__?.shareScopeMap;`,
|
|
@@ -884,21 +887,7 @@ function genBuildRemoteEntry(options, exposeAbsPaths) {
|
|
|
884
887
|
""
|
|
885
888
|
].join("\n");
|
|
886
889
|
}
|
|
887
|
-
function genApiFacade(
|
|
888
|
-
if (mode === "build") {
|
|
889
|
-
return [
|
|
890
|
-
"export {",
|
|
891
|
-
" initSharing, registerShare, registerRemotes, registerRemote, registerPlugins,",
|
|
892
|
-
" loadShare, loadRemote, getContainer, preloadRemote, parseSpec,",
|
|
893
|
-
" getRuntime, shareScopeMap, unwrapDefault, version,",
|
|
894
|
-
'} from "virtual:fulgurjs-runtime";',
|
|
895
|
-
"export { provideAppContext, getAppContext, requireAppContext } from '@fulgurjs/federation/internal/context.js';",
|
|
896
|
-
"export { definePages, validatePages } from '@fulgurjs/federation/internal/pages.js';",
|
|
897
|
-
"export { remoteComponent } from '@fulgurjs/federation/internal/vue.js';",
|
|
898
|
-
"export { default as remoteSchema } from 'virtual:fulgurjs-remote-schema';",
|
|
899
|
-
""
|
|
900
|
-
].join("\n");
|
|
901
|
-
}
|
|
890
|
+
function genApiFacade() {
|
|
902
891
|
return [
|
|
903
892
|
"export {",
|
|
904
893
|
" loadRemote, loadShare, preloadRemote, getContainer,",
|
|
@@ -907,9 +896,9 @@ function genApiFacade(mode) {
|
|
|
907
896
|
'} from "virtual:fulgurjs-runtime-proxy";',
|
|
908
897
|
"export { provideAppContext, getAppContext, requireAppContext } from '@fulgurjs/federation/internal/context.js';",
|
|
909
898
|
"export { definePages, validatePages } from '@fulgurjs/federation/internal/pages.js';",
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
"export
|
|
899
|
+
"import { createRemoteComponent } from '@fulgurjs/federation/internal/vue-adapter.js';",
|
|
900
|
+
"import { loadRemote as __fulgurjs_loadRemote } from 'virtual:fulgurjs-runtime-proxy';",
|
|
901
|
+
"export const remoteComponent = createRemoteComponent(__fulgurjs_loadRemote);",
|
|
913
902
|
""
|
|
914
903
|
].join("\n");
|
|
915
904
|
}
|
|
@@ -975,6 +964,61 @@ function ensureLexer() {
|
|
|
975
964
|
lexerReady ??= initLexer;
|
|
976
965
|
return lexerReady;
|
|
977
966
|
}
|
|
967
|
+
function splitNamedImportBindings(inner) {
|
|
968
|
+
const parts = [];
|
|
969
|
+
let start = 0;
|
|
970
|
+
for (let i = 0; i < inner.length; i++) {
|
|
971
|
+
if (inner.startsWith("/*", i)) {
|
|
972
|
+
const end = inner.indexOf("*/", i + 2);
|
|
973
|
+
i = end < 0 ? inner.length : end + 1;
|
|
974
|
+
} else if (inner.startsWith("//", i)) {
|
|
975
|
+
const end = inner.indexOf("\n", i + 2);
|
|
976
|
+
i = end < 0 ? inner.length : end;
|
|
977
|
+
} else if (inner[i] === ",") {
|
|
978
|
+
parts.push(inner.slice(start, i).trim());
|
|
979
|
+
start = i + 1;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
parts.push(inner.slice(start).trim());
|
|
983
|
+
return parts.filter(Boolean);
|
|
984
|
+
}
|
|
985
|
+
async function rewriteRuntimeEntryImports(code, exposeTarget) {
|
|
986
|
+
if (!code.includes("@fulgurjs/federation/runtime")) return null;
|
|
987
|
+
await ensureLexer();
|
|
988
|
+
const [imports] = parse(code);
|
|
989
|
+
const out = new MagicString(code);
|
|
990
|
+
let changed = false;
|
|
991
|
+
for (const imp of imports) {
|
|
992
|
+
if (imp.n !== "@fulgurjs/federation/runtime" || imp.d !== -1) continue;
|
|
993
|
+
const statement = code.slice(imp.ss, imp.se);
|
|
994
|
+
if (/^\s*import\s+type\b/.test(statement)) continue;
|
|
995
|
+
const destination = exposeTarget ? "virtual:fulgurjs-api-facade" : "@fulgurjs/federation/runtime";
|
|
996
|
+
const braces = statement.match(/\{([\s\S]*?)\}/);
|
|
997
|
+
if (braces && /^\s*import\b/.test(statement)) {
|
|
998
|
+
const parts = splitNamedImportBindings(braces[1]);
|
|
999
|
+
const normalized = parts.map((x) => x.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/g, "").trim());
|
|
1000
|
+
const schema = normalized.filter((x) => /^remoteSchema(?:\s+as\s+[A-Za-z_$][\w$]*)?$/.test(x));
|
|
1001
|
+
if (schema.length) {
|
|
1002
|
+
const rest = parts.filter((_, i) => !schema.includes(normalized[i]));
|
|
1003
|
+
const before = statement.slice(0, statement.indexOf("{")).trim();
|
|
1004
|
+
const defaultBinding = before.replace(/^import\s*/, "").replace(/,\s*$/, "").trim();
|
|
1005
|
+
const replacement = [
|
|
1006
|
+
...rest.length || defaultBinding ? [`import ${defaultBinding ? defaultBinding + (rest.length ? ", " : "") : ""}${rest.length ? `{ ${rest.join(", ")} }` : ""} from ${JSON.stringify(destination)};`] : [],
|
|
1007
|
+
`import { ${schema.join(", ")} } from "virtual:fulgurjs-remote-schema";`
|
|
1008
|
+
].join("\n");
|
|
1009
|
+
const end = code[imp.se] === ";" ? imp.se + 1 : imp.se;
|
|
1010
|
+
out.overwrite(imp.ss, end, replacement);
|
|
1011
|
+
changed = true;
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (exposeTarget) {
|
|
1016
|
+
out.overwrite(imp.s, imp.e, destination);
|
|
1017
|
+
changed = true;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return changed ? out.toString() : null;
|
|
1021
|
+
}
|
|
978
1022
|
function isExposeTargetFile(cleanPath, root, exposes) {
|
|
979
1023
|
for (const e of exposes) {
|
|
980
1024
|
const abs = path2.resolve(root, e.import.replace(/^\.\//, ""));
|
|
@@ -1341,14 +1385,6 @@ function extractTsExportNames(text) {
|
|
|
1341
1385
|
}
|
|
1342
1386
|
return [...names];
|
|
1343
1387
|
}
|
|
1344
|
-
function genRuntimeTypesShim() {
|
|
1345
|
-
return [
|
|
1346
|
-
"// \u81EA\u52A8\u751F\u6210\uFF1Afulgurjs-federation \u8FD0\u884C\u65F6\u7C7B\u578B\uFF08virtual:fulgurjs-api\uFF09",
|
|
1347
|
-
"import '@fulgurjs/federation/client'",
|
|
1348
|
-
"export {}",
|
|
1349
|
-
""
|
|
1350
|
-
].join("\n");
|
|
1351
|
-
}
|
|
1352
1388
|
function resolveDtsDir(dtsOpt, rootHasSrc) {
|
|
1353
1389
|
if (dtsOpt === false) return "";
|
|
1354
1390
|
return (typeof dtsOpt === "object" ? dtsOpt.dir : void 0) ?? (rootHasSrc ? "src/fulgurjs/types" : ".fulgurjs/types");
|
|
@@ -1386,7 +1422,6 @@ async function generateDevTypes(options, _server) {
|
|
|
1386
1422
|
const dir = resolveDtsDir(dtsOpt, fs2.existsSync(path3.join(options.root, "src")));
|
|
1387
1423
|
const outDir = path3.join(options.root, dir);
|
|
1388
1424
|
fs2.mkdirSync(outDir, { recursive: true });
|
|
1389
|
-
fs2.writeFileSync(path3.join(outDir, "fulgurjs-runtime.d.ts"), genRuntimeTypesShim());
|
|
1390
1425
|
for (const remote of options.remotes) {
|
|
1391
1426
|
if (!remote.devEntry || remote.promise) continue;
|
|
1392
1427
|
const manifest = await fetchManifest(remote.devEntry);
|
|
@@ -1633,7 +1668,10 @@ async function probeRemotesAndBuildSchema(options) {
|
|
|
1633
1668
|
}
|
|
1634
1669
|
function genEmptyRemoteSchemaModule() {
|
|
1635
1670
|
console.info("[fulgurjs] build \u671F\u8DF3\u8FC7\u8DEF\u7531 spec \u5B58\u5728\u6027\u6821\u9A8C\uFF08\u8FDC\u7A0B manifest \u4E0D\u5728\u6784\u5EFA\u673A\u672C\u5730\uFF1Bdev \u4E0B\u81EA\u52A8\u542F\u7528\uFF09");
|
|
1636
|
-
return
|
|
1671
|
+
return genRemoteSchemaModule({});
|
|
1672
|
+
}
|
|
1673
|
+
function genRemoteSchemaModule(schema) {
|
|
1674
|
+
return `export const remoteSchema = ${JSON.stringify(schema)}; export default remoteSchema`;
|
|
1637
1675
|
}
|
|
1638
1676
|
|
|
1639
1677
|
// src/vite-cache.ts
|
|
@@ -1661,7 +1699,7 @@ function syncViteCacheMarker(root, pluginVersion, log) {
|
|
|
1661
1699
|
}
|
|
1662
1700
|
|
|
1663
1701
|
// src/runtime-code.gen.ts
|
|
1664
|
-
var runtime_code_gen_default = 'var oe=/^v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z.-]+)?$/;function I(o){let i=oe.exec(String(o).trim());return i?{major:Number(i[1]),minor:Number(i[2]??0),patch:Number(i[3]??0),pre:i[4]?i[4].split("."):[]}:null}function ie(o,i){if(o.length===0&&i.length===0)return 0;if(o.length===0)return 1;if(i.length===0)return-1;let s=Math.max(o.length,i.length);for(let n=0;n<s;n++){let f=o[n],y=i[n];if(f===void 0)return-1;if(y===void 0)return 1;let R=/^\\d+$/.test(f),w=/^\\d+$/.test(y);if(R&&w){let T=Number(f)-Number(y);if(T!==0)return T}else{if(R!==w)return R?-1:1;if(f!==y)return f<y?-1:1}}return 0}function j(o,i){let s=I(o),n=I(i);return!s||!n?o<i?-1:o>i?1:0:s.major!==n.major?s.major-n.major:s.minor!==n.minor?s.minor-n.minor:s.patch!==n.patch?s.patch-n.patch:ie(s.pre,n.pre)}var se=/^[a-z]+[+:-]/i;function P(o,i){if(i===!1||i==null||i==="")return!0;let s=String(i).trim();return!s||s==="*"||s==="latest"||se.test(s)?!0:s.split("||").some(n=>ae(o,n.trim()))}function ae(o,i){if(!i||i==="*")return!I(o)?.pre.length;let s=i.split(/\\s+-\\s+/);if(s.length===2){let y=s[0].trim(),R=s[1].trim();return!(!P(o,`>=${y}`)||!P(o,`<=${R}`))}let n=I(o);if(!n)return!1;let f=ce(i);if(f===null)return!0;for(let y of f)if(!pe(n,o,y))return!1;return!(n.pre.length>0&&!f.some(y=>y.ver.pre.length>0)&&!f.some(R=>R.ver.major===n.major&&R.ver.minor===n.minor&&R.ver.patch===n.patch))}function ce(o){let i=[],s=o.trim().split(/\\s+/).filter(Boolean);if(s.length===0)return null;for(let n of s){let f=/^(>=|<=|>|<|=|\\^|~)?(.*)$/.exec(n);if(!f)return null;let y=f[1],R=f[2],w=le(y,R);if(w===null)return null;i.push(...w)}return i}function le(o,i){let s=me(i);if(!s)return null;let{ver:n,partial:f}=s;switch(o){case"^":{let y=ue(n);return y?[{op:">=",ver:n},{op:"<",ver:y}]:null}case"~":{let y=f>=2?{major:n.major,minor:n.minor+1,patch:0,pre:[]}:{major:n.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:n},{op:"<",ver:y}]}case">=":return[{op:">=",ver:n}];case">":return f===1?[{op:">=",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:">",ver:n}];case"<":return f===1?[{op:"<",ver:{major:n.major,minor:0,patch:0,pre:[]}}]:f===2?[{op:"<",ver:{major:n.major,minor:n.minor,patch:0,pre:[]}}]:[{op:"<",ver:n}];case"<=":return[{op:"<=",ver:n}];case"=":case void 0:return f===1?[{op:">=",ver:n},{op:"<",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:n},{op:"<",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:n}];default:return null}}function ue(o){return o.major>0?{major:o.major+1,minor:0,patch:0,pre:[]}:o.minor>0?{major:0,minor:o.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:o.patch+1,pre:[]}}function me(o){let i=o.replace(/^v/,"").trim();if(!i||i==="*"||i==="x"||i==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let s=i.split("."),n=[],f=0;for(let w of s.slice(0,3))if(/^\\d+$/.test(w))n.push(Number(w)),f++;else{if(w==="x"||w==="X"||w==="*")break;break}let y=i.split("-"),R=y.length>1?y.slice(1).join("-").split("+")[0].split("."):[];return f===0&&R.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:n[0]??0,minor:n[1]??0,patch:n[2]??0,pre:R},partial:f}}function fe(o,i){switch(i){case">=":return o>=0;case">":return o>0;case"<":return o<0;case"<=":return o<=0;case"=":return o===0}}function pe(o,i,s){let n=`${o.major}.${o.minor}.${o.patch}`+(o.pre.length?`-${o.pre.join(".")}`:"");if(s.upper)return!(!(j(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:""))>=0)||!(j(n,`${s.upper.major}.${s.upper.minor}.${s.upper.patch}`)<0));let f=j(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:"")),y=fe(f,s.op);return s.ver.pre.length>0&&o.pre.length===0&&(s.op===">"||s.op==="<")?!1:y}var b=class extends Error{code;details;constructor(i,s,n){super(`[fulgurjs:${i}] ${s}`),this.name="FgError",this.code=i,this.details=n}},S={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 q="3.0.0";var x=15e3,z=2,de=5,ge=3e4,he=4e3,ye=.2;function Ee(){let o=Object.create(null),i=new Map,s=[],n=new Map,f=new Map,y=new WeakMap,R=new WeakMap,w={},T=()=>{for(let e of s)try{e.init?.(w)}catch(t){console.warn("[fulgurjs] runtimePlugin init failed:",e.name,t)}},N=e=>o[e]??=Object.create(null);function $(e){try{w.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function B(e="default"){return N(e),o}function J(e,t,r,l,h={}){let a=N(e||"default"),p=Object.hasOwn(a,t)?a[t]:void 0,d=p&&typeof p=="object"?p:void 0;d||(d=Object.create(null),a[t]=d),!(Object.hasOwn(d,r)&&d[r])&&(d[r]={version:r,get:l,from:h.from??"unknown",eager:!!h.eager,loaded:!!h.loaded})}function G(e){let t=(r,l,h)=>{if(r===void 0)return;if(!(typeof r=="number"&&(h?Number.isInteger(r)&&r>=0&&r<=10:Number.isFinite(r)&&r>0)))throw new Error(`[fulgurjs] registerRemote("${e.name}"): ${l} must be a ${h?"integer 0..10":"finite positive number"}, got ${String(r)}`)};t(e.timeout,"timeout"),t(e.retries,"retries",!0),e.breaker&&(t(e.breaker.threshold,"breaker.threshold"),t(e.breaker.resetMs,"breaker.resetMs"))}function F(e){for(let t of e){G(t);let r=i.get(t.name);i.set(t.name,{timeout:x,retries:z,...r,...t,breakerThreshold:t.breaker?.threshold??r?.breakerThreshold??de,breakerResetMs:t.breaker?.resetMs??r?.breakerResetMs??ge,state:r?.state??"idle",breakerState:r?.breakerState??{fails:0,openUntil:0},entryInflight:r?.entryInflight??new Map,debug:r?.debug??{entry:t.entry,status:"idle"}})}}function X(e){F([e])}function Y(e){s.push(...e),T()}async function Z(e,t={}){let r=t.shareScope||"default",l=t.shareKey||e,a=N(r)[l]||{},p=Object.keys(a),d=t.requiredVersion,g=p.filter(c=>d===void 0||d===!1||P(c,d)),m;if(t.singleton&&p.length>0){let c=p.filter(u=>a[u].loaded);if(m=[...c.length?c:p].sort(j).pop(),p.length>1||!g.includes(m)){let u=a[m],k=`singleton skew "${l}": req "${d??"any"}" use ${m} from ${u.from}`;if(t.strictVersion){let v=new b(S.SHARE_STRICT_VERSION,k,{shareKey:l,requiredVersion:d});throw $({remote:u.from,error:v}),v}console.warn(`[fulgurjs:MFU-010] ${k}`)}}else if(m=[...g].sort(j).pop(),!m){if(t.strictVersion){let u=new b(S.SHARE_STRICT_VERSION,`no satisfying version for "${l}" (required "${d}") in share scope "${r}"`);throw $({remote:l,error:u}),u}if(t.fallback)return t.fallback();let c=new b(S.SHARE_NOT_AVAILABLE,`shared "${l}" (${d??"any"}) unavailable in scope "${r}" (no local fallback)`,{shareKey:l,requiredVersion:d});throw $({remote:l,error:c}),c}let E=a[m];if(w.resolveShare){let c=await w.resolveShare({shareKey:l,shareScope:r,requiredVersion:d,picked:E,available:Object.values(a)});c&&(E=c)}return E.loaded=!0,E.get()}function Q(e){try{let t=new URL(e,typeof location<"u"?location.href:"http://f.invalid");return t.protocol+"//"+t.host+t.pathname}catch{return String(e).replace(/[?#].*$/,"")}}function C(e,t,r){return new Promise((l,h)=>{let a=setTimeout(()=>h(new Error(`timeout after ${t}ms: ${r}`)),t);e.then(p=>{clearTimeout(a),l(p)},p=>{clearTimeout(a),h(p)})})}let ee=e=>new Promise(t=>setTimeout(t,e));function A(e,t){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${t.name}" does not export a container interface (get/init)`);if(e.name&&t.name&&e.name!==t.name){let r=`remoteEntry self-reported name "${e.name}" mismatches configured name "${t.name}"`;if(t.promise)console.warn(`[fulgurjs] ${r} (promise-based remote, continuing)`);else throw Object.assign(new Error(r),{code:S.REMOTE_NAME_MISMATCH})}}async function D(e,t){let r=t.entryInflight.get(e),l=r??import(e);return r||(t.entryInflight.set(e,l),l.catch(()=>t.entryInflight.delete(e))),C(l,t.timeout??x,`load remoteEntry ${e}`)}async function V(e,t){let r=e.shareScope||"default";if(e.container){let a=R.get(e.container);if(a&&a!==r)throw new b(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${a}", cannot re-init with "${r}"`);return e.container}if(e.containerPromise)return e.containerPromise;let l=e.breakerState;if(l.openUntil>Date.now()){let a=new b(S.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(l.openUntil).toISOString()}`,{remote:e.name});throw $({remote:e.name,error:a}),a}e.state="loading",e.debug.status="loading";let h=(async()=>{let a=[];if(e.promise)a.push(async()=>{let c=await C(e.promise(),e.timeout??x,`resolve promise remote "${e.name}"`),u=typeof c=="string"?await D(c,e):c;return A(u,e),u});else for(let c of[e.entry,...e.fallback??[]])a.push(async()=>{let u=await D(c,e);return A(u,e),u});let p,d,g=!1,m=t?.retries??e.retries??z;for(let c of a){for(let u=0;u<=m;u++){let k=performance.now();try{p=await c(),e.lastLoadMs=Math.round(performance.now()-k),e.debug.lastLoadMs=e.lastLoadMs,g=!0;break}catch(v){if(d=v,v?.code)throw v;u<m&&await ee(Math.min(he,200*2**u)*(1-ye*(1-2*Math.random())))}}if(g)break}if(!g||!p){let c=Q(e.entry),u=[];throw/^https?:\\/\\//.test(e.entry)&&typeof location<"u"?(u.push(`1. is the remote dev server running? open ${c} in a browser \\u2014 it must return JS, not HTML`),u.push("2. is the URL correct in federation({ remotes })? dev/prod entries can differ"),u.push("3. CORS: the remote dev server must allow cross-origin requests (check its server.cors)")):(u.push(`1. is the remote deployed? open ${c} in a browser \\u2014 it must return JS`),u.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS (check try_files)")),new b(S.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${c}: ${String(d?.message??d)}\n`+u.join(`\n`),{remote:e.name})}A(p,e);let E=R.get(p);if(E&&E!==r)throw new b(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${E}", cannot re-init with "${r}"`);return typeof p.init=="function"&&await p.init(o),R.set(p,r),e.container=p,e.state="loaded",e.debug.status="loaded",l.fails=0,p})();e.containerPromise=h;try{return await h}catch(a){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(a?.message??a),l.fails+=1,l.fails>=e.breakerThreshold&&(l.openUntil=Date.now()+e.breakerResetMs,l.fails=0),a instanceof b)throw $({remote:e.name,error:a}),a;if(a?.code)throw $({remote:e.name,error:a}),a;let p=new b(S.REMOTE_LOAD_FAILED,String(a?.message??a),{remote:e.name});throw $({remote:e.name,error:p}),p}}function U(e){let t=e.indexOf("/");return t===-1?{remote:e,module:""}:{remote:e.slice(0,t),module:H(e.slice(t+1))}}function H(e){return e?e.startsWith(".")?e:`./${e}`:""}async function re(e,t){let{remote:r,module:l}=U(e);try{w.beforeLoadRemote?.({remote:r,module:l})}catch(g){console.warn("[fulgurjs] beforeLoadRemote hook error (ignored):",g)}let h=i.get(r);if(!h)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${r}". Register it via federation({ remotes }) or registerRemote().`,{remote:r});let a;try{let g=l&&h.manifestUrl?K(e):Promise.resolve();[a]=await Promise.all([V(h,{retries:t?.retries}),g])}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),$({remote:r,error:g}),await t.fallbackModule();throw g}if(!l)return a;let p=`${r}@${h.shareScope||"default"}#${l}`;n.has(p)||n.set(p,a.get(l).catch(g=>{throw n.delete(p),g instanceof b||g?.code?g:new b(S.REMOTE_LOAD_FAILED,`failed to load module "${l}" from remote "${r}": ${String(g?.message??g)}`,{remote:r,module:l})}));let d;try{d=await n.get(p)}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),$({remote:r,error:g}),await t.fallbackModule();throw g}try{w.afterLoadRemote?.({remote:r,module:l,module_ns:d})}catch(g){console.warn("[fulgurjs] afterLoadRemote hook error (ignored):",g)}if(d&&typeof d=="object"&&Object.keys(d).length===0){let g=new b(S.EMPTY_EXPORTS,`no exports: ${l} @ ${r}`,{remote:r,module:l});$({remote:r,error:g}),console.error(`[fulgurjs:MFU-009] ${g.message}`)}return d}function te(e){let t=i.get(e);if(!t)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return V(t)}async function K(e,t={}){let{remote:r,module:l}=U(e),h=i.get(r);if(!h)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${r}"`,{remote:r});let a=t.mode??"preload",p=(m,E)=>{if(m.sheet)return Promise.resolve();let c=y.get(m);if(c)return c;let u=new Promise(k=>{let v=()=>{m.removeEventListener("load",v),m.removeEventListener("error",O),k()},O=()=>{$({remote:r,error:new b(S.PRELOAD_FAILED,`failed to load remote stylesheet ${E}`,{remote:r})}),v()};m.addEventListener("load",v,{once:!0}),m.addEventListener("error",O,{once:!0}),m.sheet&&v()});return y.set(m,u),u},d=(m,E)=>{if(typeof document>"u")return Promise.resolve();let c=document.querySelector(`link[href="${m}"]`);if(c)return E==="style"&&a==="preload"?y.get(c)??Promise.resolve():Promise.resolve();let u=document.createElement("link");u.rel=E==="style"?"stylesheet":"modulepreload",u.href=m,a==="prefetch"&&(u.fetchPriority="low");let k=E==="style"?p(u,m):Promise.resolve();return document.head.appendChild(u),E==="style"&&a==="preload"?k:Promise.resolve()},g=m=>{let E=typeof document<"u"?document.baseURI:void 0,c=new URL(h.entry,E||"http://fulgurjs.invalid/");return!c.pathname.endsWith("/")&&!c.pathname.split("/").pop().includes(".")&&(c.pathname+="/"),new URL(m,c).href};try{if(h.manifestUrl){let m=f.get(h.manifestUrl);m||(m=fetch(h.manifestUrl,{cache:"no-cache",signal:AbortSignal.timeout(8e3)}).then(c=>c.ok?c.json():void 0),f.set(h.manifestUrl,m),m.then(c=>{c||f.delete(h.manifestUrl)},()=>f.delete(h.manifestUrl)));let E=await m;if(E){let c=E.schemaVersion;if(typeof c=="number"&&(!Number.isInteger(c)||c>1)){$({remote:r,error:new b(S.PRELOAD_FAILED,`unsupported manifest schemaVersion ${String(c)} (expected 1)`,{remote:r})}),await d(h.entry,"modulepreload");return}await d(h.entry,"modulepreload");let u=E.exposes,k=Array.isArray(u)?u.filter(_=>_&&typeof _=="object").map(_=>[String(_.name??""),_]):u&&typeof u=="object"?Object.entries(u):[],v=l?k.filter(([_,L])=>H(String(L?.name??_))===l):k,O=[];for(let[,_]of v)if(typeof _?.file=="string"&&await d(g(_.file),"modulepreload"),Array.isArray(_?.css))for(let L of _.css){if(typeof L!="string")continue;let ne=d(g(L),"style");a==="preload"&&O.push(ne)}await Promise.all(O);return}}await d(h.entry,"modulepreload")}catch(m){$({remote:r,error:new b(S.PRELOAD_FAILED,String(m?.message??m),{remote:r})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=o,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[t,r]of i)e[t]={...r.debug,entry:r.entry};return e},errors:[]}),{shareScopeMap:o,initSharing:B,registerShare:J,registerRemotes:F,registerRemote:X,registerPlugins:Y,loadShare:Z,loadRemote:re,getContainer:te,preloadRemote:K,parseSpec:U}}var W=globalThis,M=W.__FULGURJS_RUNTIME__??Ee();W.__FULGURJS_RUNTIME__=M;try{Object.freeze(M)}catch{}var _e=q;function ke(){return M}var je=M.initSharing,Oe=M.registerShare,Te=M.registerRemotes,Le=M.registerRemote,Ie=M.registerPlugins,Pe=M.loadShare,Ne=M.loadRemote,Ae=M.getContainer,Ue=M.preloadRemote,xe=M.parseSpec,Fe=M.shareScopeMap;function Ce(o){if(o&&typeof o=="object"&&"default"in o){let i=o.default;return i!==void 0?i:o}return o}var De=M;export{De as default,Ae as getContainer,ke as getRuntime,je as initSharing,Ne as loadRemote,Pe as loadShare,xe as parseSpec,Ue as preloadRemote,Ie as registerPlugins,Le as registerRemote,Te as registerRemotes,Oe as registerShare,M as runtime,Fe as shareScopeMap,Ce as unwrapDefault,_e as version};\n';
|
|
1702
|
+
var runtime_code_gen_default = 'var oe=/^v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z.-]+)?$/;function I(o){let i=oe.exec(String(o).trim());return i?{major:Number(i[1]),minor:Number(i[2]??0),patch:Number(i[3]??0),pre:i[4]?i[4].split("."):[]}:null}function ie(o,i){if(o.length===0&&i.length===0)return 0;if(o.length===0)return 1;if(i.length===0)return-1;let s=Math.max(o.length,i.length);for(let n=0;n<s;n++){let f=o[n],y=i[n];if(f===void 0)return-1;if(y===void 0)return 1;let b=/^\\d+$/.test(f),w=/^\\d+$/.test(y);if(b&&w){let T=Number(f)-Number(y);if(T!==0)return T}else{if(b!==w)return b?-1:1;if(f!==y)return f<y?-1:1}}return 0}function O(o,i){let s=I(o),n=I(i);return!s||!n?o<i?-1:o>i?1:0:s.major!==n.major?s.major-n.major:s.minor!==n.minor?s.minor-n.minor:s.patch!==n.patch?s.patch-n.patch:ie(s.pre,n.pre)}var se=/^[a-z]+[+:-]/i;function P(o,i){if(i===!1||i==null||i==="")return!0;let s=String(i).trim();return!s||s==="*"||s==="latest"||se.test(s)?!0:s.split("||").some(n=>ae(o,n.trim()))}function ae(o,i){if(!i||i==="*")return!I(o)?.pre.length;let s=i.split(/\\s+-\\s+/);if(s.length===2){let y=s[0].trim(),b=s[1].trim();return!(!P(o,`>=${y}`)||!P(o,`<=${b}`))}let n=I(o);if(!n)return!1;let f=ce(i);if(f===null)return!0;for(let y of f)if(!pe(n,o,y))return!1;return!(n.pre.length>0&&!f.some(y=>y.ver.pre.length>0)&&!f.some(b=>b.ver.major===n.major&&b.ver.minor===n.minor&&b.ver.patch===n.patch))}function ce(o){let i=[],s=o.trim().split(/\\s+/).filter(Boolean);if(s.length===0)return null;for(let n of s){let f=/^(>=|<=|>|<|=|\\^|~)?(.*)$/.exec(n);if(!f)return null;let y=f[1],b=f[2],w=le(y,b);if(w===null)return null;i.push(...w)}return i}function le(o,i){let s=me(i);if(!s)return null;let{ver:n,partial:f}=s;switch(o){case"^":{let y=ue(n);return y?[{op:">=",ver:n},{op:"<",ver:y}]:null}case"~":{let y=f>=2?{major:n.major,minor:n.minor+1,patch:0,pre:[]}:{major:n.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:n},{op:"<",ver:y}]}case">=":return[{op:">=",ver:n}];case">":return f===1?[{op:">=",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:">",ver:n}];case"<":return f===1?[{op:"<",ver:{major:n.major,minor:0,patch:0,pre:[]}}]:f===2?[{op:"<",ver:{major:n.major,minor:n.minor,patch:0,pre:[]}}]:[{op:"<",ver:n}];case"<=":return[{op:"<=",ver:n}];case"=":case void 0:return f===1?[{op:">=",ver:n},{op:"<",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:n},{op:"<",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:n}];default:return null}}function ue(o){return o.major>0?{major:o.major+1,minor:0,patch:0,pre:[]}:o.minor>0?{major:0,minor:o.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:o.patch+1,pre:[]}}function me(o){let i=o.replace(/^v/,"").trim();if(!i||i==="*"||i==="x"||i==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let s=i.split("."),n=[],f=0;for(let w of s.slice(0,3))if(/^\\d+$/.test(w))n.push(Number(w)),f++;else{if(w==="x"||w==="X"||w==="*")break;break}let y=i.split("-"),b=y.length>1?y.slice(1).join("-").split("+")[0].split("."):[];return f===0&&b.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:n[0]??0,minor:n[1]??0,patch:n[2]??0,pre:b},partial:f}}function fe(o,i){switch(i){case">=":return o>=0;case">":return o>0;case"<":return o<0;case"<=":return o<=0;case"=":return o===0}}function pe(o,i,s){let n=`${o.major}.${o.minor}.${o.patch}`+(o.pre.length?`-${o.pre.join(".")}`:"");if(s.upper)return!(!(O(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:""))>=0)||!(O(n,`${s.upper.major}.${s.upper.minor}.${s.upper.patch}`)<0));let f=O(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:"")),y=fe(f,s.op);return s.ver.pre.length>0&&o.pre.length===0&&(s.op===">"||s.op==="<")?!1:y}var E=class extends Error{code;details;constructor(i,s,n){super(`[fulgurjs:${i}] ${s}`),this.name="FgError",this.code=i,this.details=n}},S={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 q="4.0.0";var U=15e3,z=2,de=5,ge=3e4,he=4e3,ye=.2;function Re(){let o=Object.create(null),i=new Map,s=[],n=new Map,f=new Map,y=new WeakMap,b=new WeakMap,w={},T=()=>{for(let e of s)try{e.init?.(w)}catch(t){console.warn("[fulgurjs] runtimePlugin init failed:",e.name,t)}},N=e=>o[e]??=Object.create(null);function k(e){try{w.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function B(e="default"){return N(e),o}function J(e,t,r,l,h={}){let a=N(e||"default"),p=Object.hasOwn(a,t)?a[t]:void 0,d=p&&typeof p=="object"?p:void 0;d||(d=Object.create(null),a[t]=d),!(Object.hasOwn(d,r)&&d[r])&&(d[r]={version:r,get:l,from:h.from??"unknown",eager:!!h.eager,loaded:!!h.loaded})}function G(e){let t=(r,l,h)=>{if(r===void 0)return;if(!(typeof r=="number"&&(h?Number.isInteger(r)&&r>=0&&r<=10:Number.isFinite(r)&&r>0)))throw new Error(`[fulgurjs] registerRemote("${e.name}"): ${l} must be a ${h?"integer 0..10":"finite positive number"}, got ${String(r)}`)};t(e.timeout,"timeout"),t(e.retries,"retries",!0),e.breaker&&(t(e.breaker.threshold,"breaker.threshold"),t(e.breaker.resetMs,"breaker.resetMs"))}function F(e){for(let t of e){G(t);let r=i.get(t.name);i.set(t.name,{timeout:U,retries:z,...r,...t,breakerThreshold:t.breaker?.threshold??r?.breakerThreshold??de,breakerResetMs:t.breaker?.resetMs??r?.breakerResetMs??ge,state:r?.state??"idle",breakerState:r?.breakerState??{fails:0,openUntil:0},entryInflight:r?.entryInflight??new Map,debug:r?.debug??{entry:t.entry,status:"idle"}})}}function X(e){F([e])}function Y(e){s.push(...e),T()}async function Z(e,t={}){let r=t.shareScope||"default",l=t.shareKey||e,a=N(r)[l]||{},p=Object.keys(a),d=t.requiredVersion,g=p.filter(c=>d===void 0||d===!1||P(c,d)),m;if(t.singleton&&p.length>0){let c=p.filter(u=>a[u].loaded);if(m=[...c.length?c:p].sort(O).pop(),p.length>1||!g.includes(m)){let u=a[m],_=`singleton skew "${l}": req "${d??"any"}" use ${m} from ${u.from}`;if(t.strictVersion){let $=new E(S.SHARE_STRICT_VERSION,_,{shareKey:l,requiredVersion:d});throw k({remote:u.from,error:$}),$}console.warn(`[fulgurjs:MFU-010] ${_}`)}}else if(m=[...g].sort(O).pop(),!m){if(t.strictVersion){let u=new E(S.SHARE_STRICT_VERSION,`no satisfying version for "${l}" (required "${d}") in share scope "${r}"`);throw k({remote:l,error:u}),u}if(t.fallback)return t.fallback();let c=new E(S.SHARE_NOT_AVAILABLE,`shared "${l}" (${d??"any"}) unavailable in scope "${r}" (no local fallback)`,{shareKey:l,requiredVersion:d});throw k({remote:l,error:c}),c}let R=a[m];if(w.resolveShare){let c=await w.resolveShare({shareKey:l,shareScope:r,requiredVersion:d,picked:R,available:Object.values(a)});c&&(R=c)}return R.loaded=!0,R.get()}function Q(e){try{let t=new URL(e,typeof location<"u"?location.href:"http://f.invalid");return t.protocol+"//"+t.host+t.pathname}catch{return String(e).replace(/[?#].*$/,"")}}function C(e,t,r){return new Promise((l,h)=>{let a=setTimeout(()=>h(new Error(`timeout after ${t}ms: ${r}`)),t);e.then(p=>{clearTimeout(a),l(p)},p=>{clearTimeout(a),h(p)})})}let ee=e=>new Promise(t=>setTimeout(t,e));function A(e,t){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${t.name}" does not export a container interface (get/init)`);if(e.name&&t.name&&e.name!==t.name){let r=`remoteEntry self-reported name "${e.name}" mismatches configured name "${t.name}"`;if(t.promise)console.warn(`[fulgurjs] ${r} (promise-based remote, continuing)`);else throw Object.assign(new Error(r),{code:S.REMOTE_NAME_MISMATCH})}}async function D(e,t){let r=t.entryInflight.get(e),l=r??import(e);return r||(t.entryInflight.set(e,l),l.catch(()=>t.entryInflight.delete(e))),C(l,t.timeout??U,`load remoteEntry ${e}`)}async function V(e,t){let r=e.shareScope||"default";if(e.container){let a=b.get(e.container);if(a&&a!==r)throw new E(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${a}", cannot re-init with "${r}"`);return e.container}if(e.containerPromise)return e.containerPromise;let l=e.breakerState;if(l.openUntil>Date.now()){let a=new E(S.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(l.openUntil).toISOString()}`,{remote:e.name});throw k({remote:e.name,error:a}),a}e.state="loading",e.debug.status="loading";let h=(async()=>{let a=[];if(e.promise)a.push(async()=>{let c=await C(e.promise(),e.timeout??U,`resolve promise remote "${e.name}"`),u=typeof c=="string"?await D(c,e):c;return A(u,e),u});else for(let c of[e.entry,...e.fallback??[]])a.push(async()=>{let u=await D(c,e);return A(u,e),u});let p,d,g=!1,m=t?.retries??e.retries??z;for(let c of a){for(let u=0;u<=m;u++){let _=performance.now();try{p=await c(),e.lastLoadMs=Math.round(performance.now()-_),e.debug.lastLoadMs=e.lastLoadMs,g=!0;break}catch($){if(d=$,$?.code)throw $;u<m&&await ee(Math.min(he,200*2**u)*(1-ye*(1-2*Math.random())))}}if(g)break}if(!g||!p){let c=Q(e.entry),u=[];throw/^https?:\\/\\//.test(e.entry)&&typeof location<"u"?(u.push(`1. is the remote dev server running? open ${c} in a browser \\u2014 it must return JS, not HTML`),u.push("2. is the URL correct in federation({ remotes })? dev/prod entries can differ"),u.push("3. CORS: the remote dev server must allow cross-origin requests (check its server.cors)")):(u.push(`1. is the remote deployed? open ${c} in a browser \\u2014 it must return JS`),u.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS (check try_files)")),new E(S.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${c}: ${String(d?.message??d)}\n`+u.join(`\n`),{remote:e.name})}A(p,e);let R=b.get(p);if(R&&R!==r)throw new E(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${R}", cannot re-init with "${r}"`);return typeof p.init=="function"&&await p.init(o),b.set(p,r),e.container=p,e.state="loaded",e.debug.status="loaded",l.fails=0,p})();e.containerPromise=h;try{return await h}catch(a){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(a?.message??a),l.fails+=1,l.fails>=e.breakerThreshold&&(l.openUntil=Date.now()+e.breakerResetMs,l.fails=0),a instanceof E)throw k({remote:e.name,error:a}),a;if(a?.code)throw k({remote:e.name,error:a}),a;let p=new E(S.REMOTE_LOAD_FAILED,String(a?.message??a),{remote:e.name});throw k({remote:e.name,error:p}),p}}function x(e){let t=e.indexOf("/");return t===-1?{remote:e,module:""}:{remote:e.slice(0,t),module:H(e.slice(t+1))}}function H(e){return e?e.startsWith(".")?e:`./${e}`:""}async function re(e,t){let{remote:r,module:l}=x(e);try{w.beforeLoadRemote?.({remote:r,module:l})}catch(g){console.warn("[fulgurjs] beforeLoadRemote hook error (ignored):",g)}let h=i.get(r);if(!h)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${r}". Register it via federation({ remotes }) or registerRemote().`,{remote:r});let a;try{let g=l&&h.manifestUrl?K(e):Promise.resolve();[a]=await Promise.all([V(h,{retries:t?.retries}),g])}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),k({remote:r,error:g}),await t.fallbackModule();throw g}if(!l)return a;let p=`${r}@${h.shareScope||"default"}#${l}`;n.has(p)||n.set(p,a.get(l).catch(g=>{throw n.delete(p),g instanceof E||g?.code?g:new E(S.REMOTE_LOAD_FAILED,`failed to load module "${l}" from remote "${r}": ${String(g?.message??g)}`,{remote:r,module:l})}));let d;try{d=await n.get(p)}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),k({remote:r,error:g}),await t.fallbackModule();throw g}try{w.afterLoadRemote?.({remote:r,module:l,module_ns:d})}catch(g){console.warn("[fulgurjs] afterLoadRemote hook error (ignored):",g)}if(d&&typeof d=="object"&&Object.keys(d).length===0){let g=new E(S.EMPTY_EXPORTS,`no exports: ${l} @ ${r}`,{remote:r,module:l});k({remote:r,error:g}),console.error(`[fulgurjs:MFU-009] ${g.message}`)}return d}function te(e){let t=i.get(e);if(!t)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return V(t)}async function K(e,t={}){let{remote:r,module:l}=x(e),h=i.get(r);if(!h)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${r}"`,{remote:r});let a=t.mode??"preload",p=(m,R)=>{if(m.sheet)return Promise.resolve();let c=y.get(m);if(c)return c;let u=new Promise(_=>{let $=()=>{m.removeEventListener("load",$),m.removeEventListener("error",j),_()},j=()=>{k({remote:r,error:new E(S.PRELOAD_FAILED,`failed to load remote stylesheet ${R}`,{remote:r})}),$()};m.addEventListener("load",$,{once:!0}),m.addEventListener("error",j,{once:!0}),m.sheet&&$()});return y.set(m,u),u},d=(m,R)=>{if(typeof document>"u")return Promise.resolve();let c=document.querySelector(`link[href="${m}"]`);if(c)return R==="style"&&a==="preload"?y.get(c)??Promise.resolve():Promise.resolve();let u=document.createElement("link");u.rel=R==="style"?"stylesheet":"modulepreload",u.href=m,a==="prefetch"&&(u.fetchPriority="low");let _=R==="style"?p(u,m):Promise.resolve();return document.head.appendChild(u),R==="style"&&a==="preload"?_:Promise.resolve()},g=m=>{let R=typeof document<"u"?document.baseURI:void 0,c=new URL(h.entry,R||"http://fulgurjs.invalid/");return!c.pathname.endsWith("/")&&!c.pathname.split("/").pop().includes(".")&&(c.pathname+="/"),new URL(m,c).href};try{if(h.manifestUrl){let m=f.get(h.manifestUrl);m||(m=fetch(h.manifestUrl,{cache:"no-cache",signal:AbortSignal.timeout(8e3)}).then(c=>c.ok?c.json():void 0),f.set(h.manifestUrl,m),m.then(c=>{c||f.delete(h.manifestUrl)},()=>f.delete(h.manifestUrl)));let R=await m;if(R){let c=R.schemaVersion;if(typeof c=="number"&&(!Number.isInteger(c)||c>1)){k({remote:r,error:new E(S.PRELOAD_FAILED,`unsupported manifest schemaVersion ${String(c)} (expected 1)`,{remote:r})}),await d(h.entry,"modulepreload");return}await d(h.entry,"modulepreload");let u=R.exposes,_=Array.isArray(u)?u.filter(v=>v&&typeof v=="object").map(v=>[String(v.name??""),v]):u&&typeof u=="object"?Object.entries(u):[],$=l?_.filter(([v,L])=>H(String(L?.name??v))===l):_,j=[];for(let[,v]of $)if(typeof v?.file=="string"&&await d(g(v.file),"modulepreload"),Array.isArray(v?.css))for(let L of v.css){if(typeof L!="string")continue;let ne=d(g(L),"style");a==="preload"&&j.push(ne)}await Promise.all(j);return}}await d(h.entry,"modulepreload")}catch(m){k({remote:r,error:new E(S.PRELOAD_FAILED,String(m?.message??m),{remote:r})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=o,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[t,r]of i)e[t]={...r.debug,entry:r.entry};return e},errors:[]}),{shareScopeMap:o,initSharing:B,registerShare:J,registerRemotes:F,registerRemote:X,registerPlugins:Y,loadShare:Z,loadRemote:re,getContainer:te,preloadRemote:K,parseSpec:x}}var W=globalThis,M=W.__FULGURJS_RUNTIME__??Re();W.__FULGURJS_RUNTIME__=M;try{Object.freeze(M)}catch{}var ve=q;function _e(){return M}var Oe=M.initSharing,je=M.registerShare,Te=M.registerRemotes,Le=M.registerRemote,Ie=M.registerPlugins,Pe=M.loadShare,Ne=M.loadRemote,Ae=M.getContainer,xe=M.preloadRemote,Ue=M.parseSpec,Fe=M.shareScopeMap;function Ce(o){if(o&&typeof o=="object"&&"default"in o){let i=o.default;return i!==void 0?i:o}return o}var De=M;export{De as default,Ae as getContainer,_e as getRuntime,Oe as initSharing,Ne as loadRemote,Pe as loadShare,Ue as parseSpec,xe as preloadRemote,Ie as registerPlugins,Le as registerRemote,Te as registerRemotes,je as registerShare,M as runtime,Fe as shareScopeMap,Ce as unwrapDefault,ve as version};\n';
|
|
1665
1703
|
|
|
1666
1704
|
// src/index.ts
|
|
1667
1705
|
function readRuntimeCode() {
|
|
@@ -1933,7 +1971,7 @@ export { default } from ${JSON.stringify(url)};
|
|
|
1933
1971
|
const slash = bareClean.indexOf("/");
|
|
1934
1972
|
if (slash > 0) {
|
|
1935
1973
|
const prefix = bareClean.slice(0, slash);
|
|
1936
|
-
const known = n.remotes.some((r) => r.key === prefix) || n.shared.some((sh) => sh.aliases.includes(prefix) || sh.aliases.some((a) => a.endsWith("/") && prefix.startsWith(a)));
|
|
1974
|
+
const known = bareClean === "@fulgurjs/federation/runtime" || n.remotes.some((r) => r.key === prefix) || n.shared.some((sh) => sh.aliases.includes(prefix) || sh.aliases.some((a) => a.endsWith("/") && prefix.startsWith(a)));
|
|
1937
1975
|
if (!known && !warnedUnknownPrefixes.has(prefix)) {
|
|
1938
1976
|
warnedUnknownPrefixes.add(prefix);
|
|
1939
1977
|
console.warn(
|
|
@@ -1946,7 +1984,7 @@ export { default } from ${JSON.stringify(url)};
|
|
|
1946
1984
|
if (bareClean === RUNTIME_PROXY_VIRTUAL_ID) return RESOLVED.runtimeProxy;
|
|
1947
1985
|
if (bareClean === INIT_VIRTUAL_ID) return RESOLVED.init;
|
|
1948
1986
|
if (bareClean === "virtual:fulgurjs-remote-schema") return bareClean;
|
|
1949
|
-
if (bareClean === "virtual:fulgurjs-api") return bareClean;
|
|
1987
|
+
if (bareClean === "virtual:fulgurjs-api-facade") return bareClean;
|
|
1950
1988
|
if (bareClean === "virtual:fulgurjs-provides") return RESOLVED.provides;
|
|
1951
1989
|
if (bareClean === "virtual:fulgurjs-remote-entry") return RESOLVED.remoteEntry;
|
|
1952
1990
|
if (bareClean.startsWith(SHARED_NS_FACADE_PREFIX)) {
|
|
@@ -1973,13 +2011,13 @@ export { default } from ${JSON.stringify(url)};
|
|
|
1973
2011
|
if (clean === "virtual:fulgurjs-provides" && state.normalized) {
|
|
1974
2012
|
return genDevProvides(state.normalized);
|
|
1975
2013
|
}
|
|
1976
|
-
if (clean === "virtual:fulgurjs-api") {
|
|
1977
|
-
return genApiFacade(
|
|
2014
|
+
if (clean === "virtual:fulgurjs-api-facade" && state.command === "serve") {
|
|
2015
|
+
return genApiFacade();
|
|
1978
2016
|
}
|
|
1979
2017
|
if (clean === "virtual:fulgurjs-remote-schema" && state.normalized) {
|
|
1980
2018
|
if (state.command === "build") return genEmptyRemoteSchemaModule();
|
|
1981
2019
|
remoteSchemaPromise ??= probeRemotesAndBuildSchema(state.normalized).then(
|
|
1982
|
-
|
|
2020
|
+
genRemoteSchemaModule
|
|
1983
2021
|
);
|
|
1984
2022
|
return remoteSchemaPromise;
|
|
1985
2023
|
}
|
|
@@ -2279,7 +2317,7 @@ ${code}`, map: null };
|
|
|
2279
2317
|
server.httpServer?.once("listening", () => {
|
|
2280
2318
|
setTimeout(() => {
|
|
2281
2319
|
remoteSchemaPromise ??= probeRemotesAndBuildSchema(n).then(
|
|
2282
|
-
|
|
2320
|
+
genRemoteSchemaModule
|
|
2283
2321
|
);
|
|
2284
2322
|
}, 5e3);
|
|
2285
2323
|
});
|
|
@@ -2310,17 +2348,20 @@ ${code}`, map: null };
|
|
|
2310
2348
|
async transform(code, id) {
|
|
2311
2349
|
if (!state.normalized) return null;
|
|
2312
2350
|
const clean = id.split("?")[0];
|
|
2351
|
+
const isAppSource = clean.startsWith(state.normalized.root + path6.sep) && !clean.includes(`${path6.sep}node_modules${path6.sep}`) && !clean.includes(`${path6.sep}.vite${path6.sep}`);
|
|
2352
|
+
const entryRewrite = state.command === "serve" && isAppSource ? await rewriteRuntimeEntryImports(code, isExposeTargetFile(clean, state.normalized.root, state.normalized.exposes)) : null;
|
|
2353
|
+
if (entryRewrite !== null) code = entryRewrite;
|
|
2313
2354
|
if (state.command === "serve" && code.includes("virtual:fulgurjs-runtime") && !code.includes("virtual:fulgurjs-runtime-proxy") && isExposeTargetFile(clean, state.normalized.root, state.normalized.exposes)) {
|
|
2314
2355
|
return { code: code.split("virtual:fulgurjs-runtime").join("virtual:fulgurjs-runtime-proxy"), map: null };
|
|
2315
2356
|
}
|
|
2316
|
-
if (state.command === "serve" && isPluginProcessedModule(code)) return null;
|
|
2317
|
-
if (/type=(style|template)/.test(id)) return null;
|
|
2357
|
+
if (state.command === "serve" && isPluginProcessedModule(code)) return entryRewrite === null ? null : { code, map: null };
|
|
2358
|
+
if (/type=(style|template)/.test(id)) return entryRewrite === null ? null : { code, map: null };
|
|
2318
2359
|
const isJsLike = /\.(m|c)?[jt]sx?$/.test(clean) || clean.endsWith(".vue");
|
|
2319
|
-
if (!isJsLike) return null;
|
|
2360
|
+
if (!isJsLike) return entryRewrite === null ? null : { code, map: null };
|
|
2320
2361
|
const devRewriteAll = state.command === "serve" && state.normalized.devSharedSelf;
|
|
2321
2362
|
const isPureRemoteBuild = state.normalized.exposes.length > 0 && state.normalized.remotes.length === 0;
|
|
2322
2363
|
if (state.command === "serve" && clean.includes("node_modules") && !id.includes(".vite/deps") && !devRewriteAll) {
|
|
2323
|
-
return null;
|
|
2364
|
+
return entryRewrite === null ? null : { code, map: null };
|
|
2324
2365
|
}
|
|
2325
2366
|
if (state.command === "build") {
|
|
2326
2367
|
return buildFallbackTransform(code, id);
|
|
@@ -2337,13 +2378,14 @@ ${code}`, map: null };
|
|
|
2337
2378
|
if (!cleanPath.startsWith("/")) return null;
|
|
2338
2379
|
return state.resolvedSharedPaths.get(cleanPath) ?? null;
|
|
2339
2380
|
};
|
|
2340
|
-
|
|
2381
|
+
const transformed = await transformModule(code, id, {
|
|
2341
2382
|
onRewrite: () => recordRewritten(id),
|
|
2342
2383
|
options: state.normalized,
|
|
2343
2384
|
remapSpecifier,
|
|
2344
2385
|
rewriteShared,
|
|
2345
2386
|
sharedClosureRoots: state.sharedClosureRoots
|
|
2346
2387
|
});
|
|
2388
|
+
return transformed ?? (entryRewrite === null ? null : { code, map: null });
|
|
2347
2389
|
}
|
|
2348
2390
|
};
|
|
2349
2391
|
function warmResolvedSharedPaths(server) {
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
import { Component } from 'vue';
|
|
3
|
+
|
|
4
|
+
/** 统一错误码体系(对齐 webpack ScriptExternalLoadError 等运行时错误的可诊断性) */
|
|
5
|
+
declare class FgError extends Error {
|
|
6
|
+
code: string;
|
|
7
|
+
details?: Record<string, unknown>;
|
|
8
|
+
constructor(code: string, message: string, details?: Record<string, unknown>);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ShareEntry {
|
|
12
|
+
version: string;
|
|
13
|
+
get: () => Promise<any>;
|
|
14
|
+
from: string;
|
|
15
|
+
eager: boolean;
|
|
16
|
+
loaded?: boolean;
|
|
17
|
+
}
|
|
18
|
+
type ShareScope = Record<string, Record<string, ShareEntry>>;
|
|
19
|
+
type ShareScopeMap = Record<string, ShareScope>;
|
|
20
|
+
interface RemoteConfig {
|
|
21
|
+
name: string;
|
|
22
|
+
entry: string;
|
|
23
|
+
shareScope?: string;
|
|
24
|
+
/**
|
|
25
|
+
* 加载超时 ms,默认 15000。注意:超时只代表"调用方不再等待",浏览器不会取消已发出的
|
|
26
|
+
* 动态 import——下一次调用复用同一条 in-flight 记录,不会重复初始化同一容器。
|
|
27
|
+
*/
|
|
28
|
+
timeout?: number;
|
|
29
|
+
/** 失败重试次数,默认 2(上限 10;配置期与运行时注册均校验,非法当场抛错) */
|
|
30
|
+
retries?: number;
|
|
31
|
+
/** 备用 remoteEntry 地址(首个失败后依次尝试) */
|
|
32
|
+
fallback?: string[];
|
|
33
|
+
breaker?: {
|
|
34
|
+
threshold?: number;
|
|
35
|
+
resetMs?: number;
|
|
36
|
+
};
|
|
37
|
+
/** promise-based remote:运行时解析出容器或容器地址(其解析同样受 timeout 约束) */
|
|
38
|
+
promise?: () => Promise<any>;
|
|
39
|
+
/** 内部:远程自报的发布路径(preload 用) */
|
|
40
|
+
manifestUrl?: string;
|
|
41
|
+
}
|
|
42
|
+
/** @deprecated 兼容旧版公开类型;新代码使用 RemoteConfig。 */
|
|
43
|
+
interface RemoteInput extends RemoteConfig {
|
|
44
|
+
container?: unknown;
|
|
45
|
+
containerPromise?: Promise<unknown>;
|
|
46
|
+
}
|
|
47
|
+
interface LoadRemoteOptions {
|
|
48
|
+
shareScope?: string;
|
|
49
|
+
retries?: number;
|
|
50
|
+
fallbackModule?: () => any;
|
|
51
|
+
}
|
|
52
|
+
interface PreloadRemoteOptions {
|
|
53
|
+
mode?: 'preload' | 'prefetch';
|
|
54
|
+
}
|
|
55
|
+
interface LoadShareOptions {
|
|
56
|
+
requiredVersion?: string | false;
|
|
57
|
+
singleton?: boolean;
|
|
58
|
+
strictVersion?: boolean;
|
|
59
|
+
shareKey?: string;
|
|
60
|
+
shareScope?: string;
|
|
61
|
+
/** 本地副本兜底(webpack shared.import) */
|
|
62
|
+
fallback?: () => Promise<any>;
|
|
63
|
+
}
|
|
64
|
+
interface RuntimePlugin {
|
|
65
|
+
name?: string;
|
|
66
|
+
init?: (hooks: RuntimeHooks) => void;
|
|
67
|
+
}
|
|
68
|
+
interface RuntimeHooks {
|
|
69
|
+
/** 覆写共享版本裁决结果:返回 ShareEntry 即生效 */
|
|
70
|
+
resolveShare?: (shareInfo: {
|
|
71
|
+
shareKey: string;
|
|
72
|
+
shareScope: string;
|
|
73
|
+
requiredVersion?: string | false;
|
|
74
|
+
picked?: ShareEntry;
|
|
75
|
+
available: ShareEntry[];
|
|
76
|
+
}) => Promise<ShareEntry | void> | ShareEntry | void;
|
|
77
|
+
beforeLoadRemote?: (info: {
|
|
78
|
+
remote: string;
|
|
79
|
+
module: string;
|
|
80
|
+
}) => void;
|
|
81
|
+
afterLoadRemote?: (info: {
|
|
82
|
+
remote: string;
|
|
83
|
+
module: string;
|
|
84
|
+
module_ns?: any;
|
|
85
|
+
}) => void;
|
|
86
|
+
onRemoteError?: (info: {
|
|
87
|
+
remote: string;
|
|
88
|
+
error: FgError;
|
|
89
|
+
}) => void;
|
|
90
|
+
}
|
|
91
|
+
interface RemoteDebugInfo {
|
|
92
|
+
entry: string;
|
|
93
|
+
status: 'idle' | 'loading' | 'loaded' | 'failed';
|
|
94
|
+
lastLoadMs?: number;
|
|
95
|
+
error?: string;
|
|
96
|
+
}
|
|
97
|
+
declare function createRuntime(): {
|
|
98
|
+
shareScopeMap: ShareScopeMap;
|
|
99
|
+
initSharing: (scopeName?: string) => ShareScopeMap;
|
|
100
|
+
registerShare: (scopeName: string, name: string, version: string, get: () => Promise<any>, opts?: {
|
|
101
|
+
from?: string;
|
|
102
|
+
eager?: boolean;
|
|
103
|
+
loaded?: boolean;
|
|
104
|
+
}) => void;
|
|
105
|
+
registerRemotes: (list: RemoteConfig[]) => void;
|
|
106
|
+
registerRemote: (remote: RemoteConfig) => void;
|
|
107
|
+
registerPlugins: (list: RuntimePlugin[]) => void;
|
|
108
|
+
loadShare: (name: string, opts?: LoadShareOptions) => Promise<any>;
|
|
109
|
+
loadRemote: <T = Record<string, any>>(spec: string, opts?: LoadRemoteOptions) => Promise<T>;
|
|
110
|
+
getContainer: (name: string) => Promise<any>;
|
|
111
|
+
preloadRemote: (spec: string, opts?: PreloadRemoteOptions) => Promise<void>;
|
|
112
|
+
parseSpec: (spec: string) => {
|
|
113
|
+
remote: string;
|
|
114
|
+
module: string;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
type FgRuntime = ReturnType<typeof createRuntime>;
|
|
118
|
+
/** 插件版本(与 package.json 同步维护于 src/version.ts,测试拦截漂移;用于跨源副本一致性诊断) */
|
|
119
|
+
declare const version: string;
|
|
120
|
+
/**
|
|
121
|
+
* 取当前页面生效的运行时单例(与 globalThis.__FULGURJS_RUNTIME__ 同一实例)。
|
|
122
|
+
*
|
|
123
|
+
* 远程页面禁止静态 import 'virtual:fulgurjs-runtime'——该虚拟模块由远程 dev server
|
|
124
|
+
* 求值,会在远程模块图内实例化独立的运行时副本,破坏渲染上下文
|
|
125
|
+
* (resolveComponent / withDirectives / ref owner 告警、内容区空白)。
|
|
126
|
+
* 跨源取运行时一律用本入口,或直接读全局单例。
|
|
127
|
+
*/
|
|
128
|
+
declare function getRuntime(): FgRuntime;
|
|
129
|
+
declare const initSharing: (scopeName?: string) => ShareScopeMap;
|
|
130
|
+
declare const registerShare: (scopeName: string, name: string, version: string, get: () => Promise<any>, opts?: {
|
|
131
|
+
from?: string;
|
|
132
|
+
eager?: boolean;
|
|
133
|
+
loaded?: boolean;
|
|
134
|
+
}) => void;
|
|
135
|
+
declare const registerRemotes: (list: RemoteConfig[]) => void;
|
|
136
|
+
declare const registerRemote: (remote: RemoteConfig) => void;
|
|
137
|
+
declare const registerPlugins: (list: RuntimePlugin[]) => void;
|
|
138
|
+
declare const loadShare: (name: string, opts?: LoadShareOptions) => Promise<any>;
|
|
139
|
+
declare const loadRemote: <T = Record<string, any>>(spec: string, opts?: LoadRemoteOptions) => Promise<T>;
|
|
140
|
+
declare const getContainer: (name: string) => Promise<any>;
|
|
141
|
+
declare const preloadRemote: (spec: string, opts?: PreloadRemoteOptions) => Promise<void>;
|
|
142
|
+
declare const parseSpec: (spec: string) => {
|
|
143
|
+
remote: string;
|
|
144
|
+
module: string;
|
|
145
|
+
};
|
|
146
|
+
declare const shareScopeMap: ShareScopeMap;
|
|
147
|
+
/** default 导出 interop:ESM 取 .default;CJS 命名空间回退整体 */
|
|
148
|
+
declare function unwrapDefault(ns: any): any;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 跨应用上下文标准字段表(§4.3,0.8.2 精简后)。
|
|
152
|
+
*
|
|
153
|
+
* 读写约定:宿主桥先写标准字段;远程 boot 只增不改宿主键;
|
|
154
|
+
* 嵌套对象(如 events)是引用共享,子应用挂属性即时可见(同 realm 直引用)。
|
|
155
|
+
*
|
|
156
|
+
* 精简记录(0.8.2):`token` 快照与 `formUrl`/`baseUrl` 从默认 provide 集合移除——
|
|
157
|
+
* token 快照与 getToken 函数引用重复(快照会过期),formUrl/baseUrl 自 0.7.0
|
|
158
|
+
* remoteComponent 直渲染后无消费点;项目如需可经扩展位自行提供。
|
|
159
|
+
*/
|
|
160
|
+
interface AppContext {
|
|
161
|
+
/** 宿主登录用户原始形态(只读约定) */
|
|
162
|
+
user: Record<string, any>;
|
|
163
|
+
/** 取最新 token(拉取式防过期;0.8.2 起 bridge 不再传一次性 token 快照,用本函数取值) */
|
|
164
|
+
getToken?: () => string | undefined;
|
|
165
|
+
/** 宿主 pinia 实例:子应用 useUserStore(ctx.store) 拿共享响应式状态 */
|
|
166
|
+
store?: unknown;
|
|
167
|
+
/** 宿主 Vue App 实例(同 realm 直引用):全局组件/指令注册目标 */
|
|
168
|
+
hostApp?: unknown;
|
|
169
|
+
/** EP locale 等 UI 配置(原 W4 字段) */
|
|
170
|
+
locale?: unknown;
|
|
171
|
+
/** 事件/方法池:events.main.* 宿主提供、events.bpm.* / events.lowcode.* 子应用反向注册 */
|
|
172
|
+
events?: Record<string, any>;
|
|
173
|
+
/** 项目扩展位(formUrl/baseUrl 等自定义键,按需自行提供) */
|
|
174
|
+
[key: string]: unknown;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 宿主写入跨应用上下文(merge 语义,幂等可多次调用,后写覆盖同键)。
|
|
178
|
+
*
|
|
179
|
+
* 宿主桥(host/src/fulgurjs/host/bridge.ts)在登录完成后调用一次:
|
|
180
|
+
* provideAppContext({ user, token, getToken, store, hostApp, locale, events: { main: mainEvents }, ... })
|
|
181
|
+
*/
|
|
182
|
+
declare function provideAppContext(config: Partial<AppContext> & Record<string, unknown>): void;
|
|
183
|
+
/**
|
|
184
|
+
* 读上下文快照(传输层快照:顶层 merge 结果 + 嵌套对象引用共享)。
|
|
185
|
+
* 页面无运行时单例(独立直开远程页)→ CC-002 显式抛错,不静默回空。
|
|
186
|
+
*/
|
|
187
|
+
declare function getAppContext(): AppContext;
|
|
188
|
+
/**
|
|
189
|
+
* 显式校验读取(远程 boot 消费入口):任一键缺失 → CC-001 三段式。
|
|
190
|
+
*
|
|
191
|
+
* 用法:const { store, user, hostApp } = requireAppContext('store', 'user', 'hostApp')
|
|
192
|
+
* 时序契约:宿主 bridge 先 provide,远程 federatedBoot 后 require——违反即在 boot 处显式失败。
|
|
193
|
+
*/
|
|
194
|
+
declare function requireAppContext(...keys: string[]): AppContext;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* D.2 宿主路由表校验器(definePages)
|
|
198
|
+
*
|
|
199
|
+
* 背景:带参路由缺省推导 spec 时会剥离 :参数 段,可能与其它条目(如列表页)的
|
|
200
|
+
* expose 键收敛相同 → 静默加载错误组件(真实事故:复制流程误走更新语义)。
|
|
201
|
+
*
|
|
202
|
+
* 定位:纯同步纯函数,dev(宿主浏览器模块求值)与 build(node)行为一致;
|
|
203
|
+
* 只校验不改写入参;ERROR 级聚合一次 throw(strict:false 降级 console.error),
|
|
204
|
+
* WARN 级聚合 console.warn。
|
|
205
|
+
*
|
|
206
|
+
* 规则:
|
|
207
|
+
* - R1 [ERROR] 带参路由(无显式 spec)的推导 spec 与任一其它条目的有效 spec 相同
|
|
208
|
+
* - R2 [WARN] 多条目的有效 spec 完全相同(可能是刻意的菜单别名,要求有意识)
|
|
209
|
+
* - R3 [ERROR] schema 提供时:有效 spec 的 exposes 键不在对应 remote 清单中
|
|
210
|
+
* (把运行时 MFU-006 提前到启动期;schema 缺失/remote 不可达则跳过)
|
|
211
|
+
* - R4 [ERROR] 静态路由被数组中更靠前的带参路由遮蔽(先到先得 → 静态路由成死路由);
|
|
212
|
+
* 含路由完全重复
|
|
213
|
+
* - R5 [WARN] name 字段重复(vue-router 命名跳转歧义)
|
|
214
|
+
*/
|
|
215
|
+
interface PageRouteLike {
|
|
216
|
+
/** 宿主路由路径(:param 段) */
|
|
217
|
+
route: string;
|
|
218
|
+
/** 显式 spec(缺省走推导) */
|
|
219
|
+
spec?: string;
|
|
220
|
+
/** 其余字段(name/title/...)由宿主自由扩展,校验器按需读取 */
|
|
221
|
+
name?: string;
|
|
222
|
+
[key: string]: unknown;
|
|
223
|
+
}
|
|
224
|
+
interface RemoteSchemaEntry {
|
|
225
|
+
/** 该 remote 的 exposes 键清单(与 spec 同口径,剥 ./ 前缀比较) */
|
|
226
|
+
exposes: string[];
|
|
227
|
+
/** manifest 是否成功拉取(false 时跳过该 remote 的 R3,诚实降级) */
|
|
228
|
+
exists?: boolean;
|
|
229
|
+
}
|
|
230
|
+
interface PagesOptions {
|
|
231
|
+
/**
|
|
232
|
+
* 带参路由的缺省 spec 推导规则(宿主私有约定,如
|
|
233
|
+
* (route) => `pages/${route 去前缀去 :参}`)。
|
|
234
|
+
* 缺省 = 去掉首段(远程前缀)+ 剥 :参 段(无 pages/ 前缀)——
|
|
235
|
+
* 推导只需在全部条目间自洽即可保持冲突判定成立。
|
|
236
|
+
*/
|
|
237
|
+
deriveSpec?: (route: string) => string;
|
|
238
|
+
/** 路由前缀 → remote 名(R3 用:{'/remote-a/': 'remote-a'});缺省跳过 R3 */
|
|
239
|
+
remotes?: Record<string, string>;
|
|
240
|
+
/** remote exposes 清单(dev 由 virtual:fulgurjs-remote-schema 提供);缺省跳过 R3 */
|
|
241
|
+
schema?: Record<string, RemoteSchemaEntry>;
|
|
242
|
+
/** false = ERROR 降级 console.error(默认 true = throw) */
|
|
243
|
+
strict?: boolean;
|
|
244
|
+
}
|
|
245
|
+
interface PageViolation {
|
|
246
|
+
rule: 'R1' | 'R2' | 'R3' | 'R4' | 'R5';
|
|
247
|
+
level: 'error' | 'warn';
|
|
248
|
+
message: string;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 校验路由表(独立导出便于单测):返回违例清单(不抛错)。
|
|
252
|
+
*/
|
|
253
|
+
declare function validatePages(pages: PageRouteLike[], options?: PagesOptions): PageViolation[];
|
|
254
|
+
/**
|
|
255
|
+
* 宿主路由表定义入口:校验(聚合报错)后原样返回入参,不改写任何字段。
|
|
256
|
+
* 违反 ERROR 级规则时默认 throw(dev overlay / build 失败直接可见);
|
|
257
|
+
* strict: false 时降级 console.error。WARN 级始终 console.warn。
|
|
258
|
+
*/
|
|
259
|
+
declare function definePages<P extends PageRouteLike[]>(pages: P, options?: PagesOptions): P;
|
|
260
|
+
|
|
261
|
+
/** Vue 适配层只接收加载函数,不静态引用运行时内核。 */
|
|
262
|
+
|
|
263
|
+
interface RemoteComponentOptions {
|
|
264
|
+
loadingComponent?: Component;
|
|
265
|
+
errorComponent?: Component;
|
|
266
|
+
retries?: number;
|
|
267
|
+
delay?: number;
|
|
268
|
+
timeout?: number;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
declare const remoteComponent: (spec: string, opts?: RemoteComponentOptions) => vue.Component;
|
|
272
|
+
|
|
273
|
+
/** 浏览器应用唯一公开入口。 */
|
|
274
|
+
|
|
275
|
+
type RemoteSchema = Record<string, RemoteSchemaEntry>;
|
|
276
|
+
/** 无插件转换的场景(构建、Node 导入)如实返回空清单。 */
|
|
277
|
+
declare const remoteSchema: RemoteSchema;
|
|
278
|
+
|
|
279
|
+
export { type AppContext, type FgRuntime, type LoadRemoteOptions, type LoadShareOptions, type PageRouteLike, type PageViolation, type PagesOptions, type PreloadRemoteOptions, type RemoteComponentOptions, type RemoteConfig, type RemoteDebugInfo, type RemoteInput, type RemoteSchema, type RemoteSchemaEntry, type RuntimeHooks, type RuntimePlugin, type ShareEntry, type ShareScope, type ShareScopeMap, definePages, getAppContext, getContainer, getRuntime, initSharing, loadRemote, loadShare, parseSpec, preloadRemote, provideAppContext, registerPlugins, registerRemote, registerRemotes, registerShare, remoteComponent, remoteSchema, requireAppContext, shareScopeMap, unwrapDefault, validatePages, version };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { initSharing, registerShare, registerRemotes, registerRemote, registerPlugins, loadShare, loadRemote, getContainer, preloadRemote, parseSpec, getRuntime, shareScopeMap, unwrapDefault, version } from "./runtime.js";
|
|
2
|
+
export { provideAppContext, getAppContext, requireAppContext } from "./context.js";
|
|
3
|
+
export { definePages, validatePages } from "./pages.js";
|
|
4
|
+
export { remoteComponent } from "./vue.js";
|
|
5
|
+
export const remoteSchema = {};
|