@qiankunjs/shared 0.0.1-rc.3 → 0.0.1-rc.5
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/cjs/assets-transpilers/index.d.ts +8 -0
- package/dist/cjs/assets-transpilers/index.js +14 -0
- package/dist/cjs/assets-transpilers/index.js.map +1 -1
- package/dist/cjs/assets-transpilers/script.d.ts +2 -2
- package/dist/cjs/assets-transpilers/script.js +110 -74
- package/dist/cjs/assets-transpilers/script.js.map +1 -1
- package/dist/cjs/assets-transpilers/types.d.ts +11 -2
- package/dist/cjs/assets-transpilers/types.js +1 -2
- package/dist/cjs/assets-transpilers/types.js.map +1 -1
- package/dist/cjs/assets-transpilers/utils.d.ts +1 -0
- package/dist/cjs/assets-transpilers/utils.js +6 -3
- package/dist/cjs/assets-transpilers/utils.js.map +1 -1
- package/dist/cjs/error/QiankunError.js +1 -2
- package/dist/cjs/error/QiankunError.js.map +1 -1
- package/dist/cjs/utils.d.ts +8 -0
- package/dist/cjs/utils.js +89 -28
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/assets-transpilers/index.d.ts +8 -0
- package/dist/esm/assets-transpilers/index.js +8 -0
- package/dist/esm/assets-transpilers/index.js.map +1 -1
- package/dist/esm/assets-transpilers/script.d.ts +2 -2
- package/dist/esm/assets-transpilers/script.js +110 -73
- package/dist/esm/assets-transpilers/script.js.map +1 -1
- package/dist/esm/assets-transpilers/types.d.ts +11 -2
- package/dist/esm/assets-transpilers/types.js.map +1 -1
- package/dist/esm/assets-transpilers/utils.d.ts +1 -0
- package/dist/esm/assets-transpilers/utils.js +4 -0
- package/dist/esm/assets-transpilers/utils.js.map +1 -1
- package/dist/esm/utils.d.ts +8 -0
- package/dist/esm/utils.js +78 -12
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -7
- package/src/assets-transpilers/index.ts +0 -40
- package/src/assets-transpilers/link.ts +0 -130
- package/src/assets-transpilers/script.ts +0 -175
- package/src/assets-transpilers/types.ts +0 -22
- package/src/assets-transpilers/utils.ts +0 -16
- package/src/common.ts +0 -3
- package/src/error/QiankunError.ts +0 -5
- package/src/error/index.ts +0 -1
- package/src/index.ts +0 -9
- package/src/module-resolver/__tests__/index.ts +0 -75
- package/src/module-resolver/index.ts +0 -92
- package/src/module-resolver/types.ts +0 -9
- package/src/typings.d.ts +0 -13
- package/src/utils.ts +0 -29
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Kuitos
|
|
3
|
-
* @since 2023-04-26
|
|
4
|
-
*/
|
|
5
|
-
import type { MatchResult } from '../module-resolver';
|
|
6
|
-
import { getEntireUrl } from '../utils';
|
|
7
|
-
import { preTranspile as preTranspileScript } from './script';
|
|
8
|
-
import type { AssetsTranspilerOpts, BaseTranspilerOpts } from './types';
|
|
9
|
-
import { Mode } from './types';
|
|
10
|
-
import { createReusingObjectUrl } from './utils';
|
|
11
|
-
|
|
12
|
-
type PreTranspileResult =
|
|
13
|
-
| { mode: Mode.REUSED_DEP_IN_SANDBOX; result: { src: string } & MatchResult }
|
|
14
|
-
| { mode: Mode.NONE; result?: never };
|
|
15
|
-
const preTranspileStyleSheetLink = (
|
|
16
|
-
link: Partial<Pick<HTMLLinkElement, 'href' | 'rel'>>,
|
|
17
|
-
baseURI: string,
|
|
18
|
-
opts: BaseTranspilerOpts,
|
|
19
|
-
): PreTranspileResult => {
|
|
20
|
-
const { sandbox, moduleResolver } = opts;
|
|
21
|
-
const { href, rel } = link;
|
|
22
|
-
|
|
23
|
-
if (sandbox) {
|
|
24
|
-
// filter preload links
|
|
25
|
-
if (href && rel === 'stylesheet') {
|
|
26
|
-
const linkHref = getEntireUrl(href, baseURI);
|
|
27
|
-
|
|
28
|
-
const matchedAssets = moduleResolver?.(linkHref);
|
|
29
|
-
if (matchedAssets) {
|
|
30
|
-
return {
|
|
31
|
-
mode: Mode.REUSED_DEP_IN_SANDBOX,
|
|
32
|
-
result: { src: linkHref, ...matchedAssets },
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
mode: Mode.NONE,
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const postProcessPreloadLink = (link: HTMLLinkElement, baseURI: string, opts: AssetsTranspilerOpts): void => {
|
|
44
|
-
const { as, href } = link;
|
|
45
|
-
switch (as) {
|
|
46
|
-
case 'script': {
|
|
47
|
-
const { mode, result } = preTranspileScript({ src: href }, baseURI, opts);
|
|
48
|
-
|
|
49
|
-
switch (mode) {
|
|
50
|
-
/**
|
|
51
|
-
* While the assets are transpiling in sandbox, it means they will be evaluated with manual fetching,
|
|
52
|
-
* thus we need to set the attribute `as` to fetch instead of script or style to avoid preload cache missing.
|
|
53
|
-
* see https://stackoverflow.com/questions/52635660/can-link-rel-preload-be-made-to-work-with-fetch/63814972#63814972
|
|
54
|
-
*/
|
|
55
|
-
case Mode.REMOTE_ASSETS_IN_SANDBOX: {
|
|
56
|
-
link.as = 'fetch';
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
case Mode.REUSED_DEP_IN_SANDBOX: {
|
|
61
|
-
const { url } = result;
|
|
62
|
-
link.href = createReusingObjectUrl(href, url, 'text/javascript');
|
|
63
|
-
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
case 'style': {
|
|
72
|
-
const { mode, result } = preTranspileStyleSheetLink({ href, rel: 'stylesheet' }, baseURI, opts);
|
|
73
|
-
|
|
74
|
-
switch (mode) {
|
|
75
|
-
case Mode.REUSED_DEP_IN_SANDBOX: {
|
|
76
|
-
const { url } = result;
|
|
77
|
-
link.href = createReusingObjectUrl(href, url, 'text/css');
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
default:
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export default function transpileLink(
|
|
91
|
-
link: HTMLLinkElement,
|
|
92
|
-
baseURI: string,
|
|
93
|
-
opts: AssetsTranspilerOpts,
|
|
94
|
-
): HTMLLinkElement {
|
|
95
|
-
const hrefAttribute = link.getAttribute('href');
|
|
96
|
-
const { mode, result } = preTranspileStyleSheetLink(
|
|
97
|
-
{
|
|
98
|
-
href: hrefAttribute || undefined,
|
|
99
|
-
rel: link.rel,
|
|
100
|
-
},
|
|
101
|
-
baseURI,
|
|
102
|
-
opts,
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
switch (mode) {
|
|
106
|
-
case Mode.REUSED_DEP_IN_SANDBOX: {
|
|
107
|
-
const { src, version, url } = result;
|
|
108
|
-
link.dataset.href = src;
|
|
109
|
-
link.dataset.version = version;
|
|
110
|
-
link.href = createReusingObjectUrl(src, url, 'text/css');
|
|
111
|
-
|
|
112
|
-
return link;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
case Mode.NONE:
|
|
116
|
-
default: {
|
|
117
|
-
if (hrefAttribute) {
|
|
118
|
-
link.href = getEntireUrl(hrefAttribute, baseURI);
|
|
119
|
-
|
|
120
|
-
if (link.rel === 'preload') {
|
|
121
|
-
postProcessPreloadLink(link, baseURI, opts);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return link;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return link;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Kuitos
|
|
3
|
-
* @since 2023-03-16
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { MatchResult } from '../module-resolver';
|
|
7
|
-
import { getEntireUrl } from '../utils';
|
|
8
|
-
import type { AssetsTranspilerOpts } from './types';
|
|
9
|
-
import { Mode } from './types';
|
|
10
|
-
import { createReusingObjectUrl } from './utils';
|
|
11
|
-
|
|
12
|
-
const isValidJavaScriptType = (type?: string): boolean => {
|
|
13
|
-
const handleTypes = [
|
|
14
|
-
'text/javascript',
|
|
15
|
-
'module',
|
|
16
|
-
'application/javascript',
|
|
17
|
-
'text/ecmascript',
|
|
18
|
-
'application/ecmascript',
|
|
19
|
-
];
|
|
20
|
-
return !type || handleTypes.indexOf(type) !== -1;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const getCredentials = (crossOrigin: string | null): RequestInit['credentials'] | undefined => {
|
|
24
|
-
switch (crossOrigin) {
|
|
25
|
-
case 'anonymous':
|
|
26
|
-
return 'same-origin';
|
|
27
|
-
case 'use-credentials':
|
|
28
|
-
return 'include';
|
|
29
|
-
default:
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type PreTranspileResult =
|
|
35
|
-
| { mode: Mode.REMOTE_ASSETS_IN_SANDBOX; result: { src: string } }
|
|
36
|
-
| { mode: Mode.REUSED_DEP_IN_SANDBOX; result: { src: string } & MatchResult }
|
|
37
|
-
| { mode: Mode.INLINE_CODE_IN_SANDBOX; result: { code: string } }
|
|
38
|
-
| { mode: Mode.NONE; result?: never };
|
|
39
|
-
|
|
40
|
-
export const preTranspile = (
|
|
41
|
-
script: Partial<Pick<HTMLScriptElement, 'src' | 'type' | 'textContent'>>,
|
|
42
|
-
baseURI: string,
|
|
43
|
-
opts: AssetsTranspilerOpts,
|
|
44
|
-
): PreTranspileResult => {
|
|
45
|
-
const { sandbox, moduleResolver } = opts;
|
|
46
|
-
|
|
47
|
-
const { src, type } = script;
|
|
48
|
-
|
|
49
|
-
if (sandbox) {
|
|
50
|
-
if (src) {
|
|
51
|
-
const entireUrl = getEntireUrl(src, baseURI);
|
|
52
|
-
const matchedScript = moduleResolver?.(entireUrl);
|
|
53
|
-
if (matchedScript) {
|
|
54
|
-
return {
|
|
55
|
-
mode: Mode.REUSED_DEP_IN_SANDBOX,
|
|
56
|
-
result: { src: entireUrl, ...matchedScript },
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
mode: Mode.REMOTE_ASSETS_IN_SANDBOX,
|
|
62
|
-
result: { src: entireUrl },
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (isValidJavaScriptType(type)) {
|
|
67
|
-
const rawNode = opts.rawNode as HTMLScriptElement;
|
|
68
|
-
const scriptNode = script.textContent ? script : rawNode.childNodes[0];
|
|
69
|
-
|
|
70
|
-
const code = scriptNode.textContent;
|
|
71
|
-
if (code) {
|
|
72
|
-
return {
|
|
73
|
-
mode: Mode.INLINE_CODE_IN_SANDBOX,
|
|
74
|
-
result: {
|
|
75
|
-
code,
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return { mode: Mode.NONE };
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export default function transpileScript(
|
|
86
|
-
script: HTMLScriptElement,
|
|
87
|
-
baseURI: string,
|
|
88
|
-
opts: AssetsTranspilerOpts,
|
|
89
|
-
): HTMLScriptElement {
|
|
90
|
-
// Can't use script.src directly, because it will be resolved to absolute path by browser with Node.baseURI
|
|
91
|
-
// Such as <script src="./foo.js"></script> will be resolved to http://localhost:8000/foo.js while read script.src
|
|
92
|
-
const srcAttribute = script.getAttribute('src');
|
|
93
|
-
const { sandbox, fetch } = opts;
|
|
94
|
-
|
|
95
|
-
const { mode, result } = preTranspile(
|
|
96
|
-
{
|
|
97
|
-
src: srcAttribute || undefined,
|
|
98
|
-
type: script.type,
|
|
99
|
-
textContent: script.textContent,
|
|
100
|
-
},
|
|
101
|
-
baseURI,
|
|
102
|
-
opts,
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
switch (mode) {
|
|
106
|
-
case Mode.REMOTE_ASSETS_IN_SANDBOX: {
|
|
107
|
-
const { src } = result;
|
|
108
|
-
|
|
109
|
-
// We must remove script src to avoid self execution as we need to fetch the script content and transpile it
|
|
110
|
-
script.removeAttribute('src');
|
|
111
|
-
script.dataset.src = src;
|
|
112
|
-
|
|
113
|
-
const syncMode = !script.hasAttribute('async');
|
|
114
|
-
const priority: Priority = syncMode ? 'high' : 'low';
|
|
115
|
-
const credentials = getCredentials(script.crossOrigin);
|
|
116
|
-
|
|
117
|
-
void fetch(src, { credentials, priority })
|
|
118
|
-
.then((res) => res.text())
|
|
119
|
-
.then((code) => {
|
|
120
|
-
const codeFactory = sandbox!.makeEvaluateFactory(code, src);
|
|
121
|
-
|
|
122
|
-
// HTMLScriptElement default fetchPriority is 'auto', we should set it to 'high' to make it execute earlier while it's not async script
|
|
123
|
-
if (syncMode) {
|
|
124
|
-
script.fetchPriority = 'high';
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
script.src = URL.createObjectURL(new Blob([codeFactory], { type: 'text/javascript' }));
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return script;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
case Mode.INLINE_CODE_IN_SANDBOX: {
|
|
134
|
-
const rawNode = opts.rawNode as HTMLScriptElement;
|
|
135
|
-
const scriptNode = script.textContent ? script : rawNode.childNodes[0];
|
|
136
|
-
const { code } = result;
|
|
137
|
-
|
|
138
|
-
scriptNode.textContent = sandbox!.makeEvaluateFactory(code, baseURI);
|
|
139
|
-
// mark the script have consumed
|
|
140
|
-
script.dataset.consumed = 'true';
|
|
141
|
-
|
|
142
|
-
return script;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
case Mode.REUSED_DEP_IN_SANDBOX: {
|
|
146
|
-
const { url, version, src } = result;
|
|
147
|
-
|
|
148
|
-
script.dataset.src = src;
|
|
149
|
-
script.dataset.version = version;
|
|
150
|
-
|
|
151
|
-
const syncMode = !script.getAttribute('async');
|
|
152
|
-
// HTMLScriptElement default fetchPriority is 'auto', we should set it to 'high' to make it execute earlier while it's not async script
|
|
153
|
-
if (syncMode) {
|
|
154
|
-
script.fetchPriority = 'high';
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// When the script hits the dependency reuse logic, the current script is not executed, and an empty script is returned directly
|
|
158
|
-
script.src = createReusingObjectUrl(src, url, 'text/javascript');
|
|
159
|
-
|
|
160
|
-
return script;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
case Mode.NONE:
|
|
164
|
-
default: {
|
|
165
|
-
if (srcAttribute) {
|
|
166
|
-
script.src = getEntireUrl(srcAttribute, baseURI);
|
|
167
|
-
return script;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return script;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// TODO find entry exports
|
|
175
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Kuitos
|
|
3
|
-
* @since 2023-08-26
|
|
4
|
-
*/
|
|
5
|
-
import type { Sandbox } from '@qiankunjs/sandbox';
|
|
6
|
-
import type { BaseLoaderOpts } from '../common';
|
|
7
|
-
|
|
8
|
-
import type { MatchResult } from '../module-resolver';
|
|
9
|
-
|
|
10
|
-
export type BaseTranspilerOpts = BaseLoaderOpts & {
|
|
11
|
-
moduleResolver?: (url: string) => MatchResult | undefined;
|
|
12
|
-
sandbox?: Sandbox;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type AssetsTranspilerOpts = BaseTranspilerOpts & { rawNode: Node };
|
|
16
|
-
|
|
17
|
-
export enum Mode {
|
|
18
|
-
REMOTE_ASSETS_IN_SANDBOX = 'RAIS',
|
|
19
|
-
REUSED_DEP_IN_SANDBOX = 'RDIS',
|
|
20
|
-
INLINE_CODE_IN_SANDBOX = 'ICIS',
|
|
21
|
-
NONE = 'NONE',
|
|
22
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Kuitos
|
|
3
|
-
* @since 2023-10-09
|
|
4
|
-
*/
|
|
5
|
-
import { memoize } from 'lodash';
|
|
6
|
-
|
|
7
|
-
export const createReusingObjectUrl = memoize(
|
|
8
|
-
(src: string, url: string, type: 'text/javascript' | 'text/css'): string => {
|
|
9
|
-
return URL.createObjectURL(
|
|
10
|
-
new Blob([`/* ${src} is reusing the execution result of ${url} */`], {
|
|
11
|
-
type,
|
|
12
|
-
}),
|
|
13
|
-
);
|
|
14
|
-
},
|
|
15
|
-
(src, url, type) => `${src}#${url}#${type}`,
|
|
16
|
-
);
|
package/src/common.ts
DELETED
package/src/error/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { QiankunError } from './QiankunError';
|
package/src/index.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { moduleResolver } from '../index';
|
|
4
|
-
|
|
5
|
-
describe('default module resolver', () => {
|
|
6
|
-
const mainAppContainer = document.createElement('div');
|
|
7
|
-
mainAppContainer.innerHTML = `
|
|
8
|
-
<script type="dependencymap">
|
|
9
|
-
{
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"moment": {
|
|
12
|
-
"url": "https://unpkg.com/2.1.1/moment.js",
|
|
13
|
-
"version": "2.1.1",
|
|
14
|
-
"range": "^2.0.1"
|
|
15
|
-
},
|
|
16
|
-
"lodash": {
|
|
17
|
-
"url": "https://unpkg.com/4.0.2/lodash.js",
|
|
18
|
-
"version": "4.0.2",
|
|
19
|
-
"range": "~4.0.1"
|
|
20
|
-
},
|
|
21
|
-
"antd": {
|
|
22
|
-
"url": "https://unpkg.com/4.0.2/antd",
|
|
23
|
-
"version": "4.0.2",
|
|
24
|
-
"range": "~4.0.1"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
</script>
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
it('should works well', ({ expect }) => {
|
|
32
|
-
const microAppContainer = document.createElement('div');
|
|
33
|
-
microAppContainer.innerHTML = `
|
|
34
|
-
<script type="dependencymap">
|
|
35
|
-
{
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"moment": {
|
|
38
|
-
"url": "https://unpkg.com/2.0.1/moment.js",
|
|
39
|
-
"version": "2.0.1",
|
|
40
|
-
"range": "^2.0.1"
|
|
41
|
-
},
|
|
42
|
-
"lodash": {
|
|
43
|
-
"url": "https://unpkg.com/4.0.1/lodash.js",
|
|
44
|
-
"version": "4.0.1",
|
|
45
|
-
"range": "~4.0.1"
|
|
46
|
-
},
|
|
47
|
-
"antd": {
|
|
48
|
-
"url": "https://unpkg.com/4.0.1/antd",
|
|
49
|
-
"version": "4.0.1",
|
|
50
|
-
"range": "4.0.1"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
</script>
|
|
55
|
-
`;
|
|
56
|
-
|
|
57
|
-
const result1 = moduleResolver('https://unpkg.com/4.0.1/antd', microAppContainer, mainAppContainer);
|
|
58
|
-
expect(result1).toBeUndefined();
|
|
59
|
-
|
|
60
|
-
const result2 = moduleResolver('https://unpkg.com/4.0.1/lodash.js', microAppContainer, mainAppContainer);
|
|
61
|
-
expect(result2).toStrictEqual({
|
|
62
|
-
version: '4.0.2',
|
|
63
|
-
url: 'https://unpkg.com/4.0.2/lodash.js',
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const result3 = moduleResolver('https://unpkg.com/2.0.1/moment.js', microAppContainer, mainAppContainer);
|
|
67
|
-
expect(result3).toStrictEqual({
|
|
68
|
-
version: '2.1.1',
|
|
69
|
-
url: 'https://unpkg.com/2.1.1/moment.js',
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const result4 = moduleResolver('https://unpkg.com/4.0.2/antd', microAppContainer, mainAppContainer);
|
|
73
|
-
expect(result4).toBeUndefined();
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import satisfies from 'semver/functions/satisfies';
|
|
2
|
-
import type { MatchResult } from './types';
|
|
3
|
-
|
|
4
|
-
declare global {
|
|
5
|
-
interface HTMLElement {
|
|
6
|
-
__matched_deps__?: string[];
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type Dependency = {
|
|
11
|
-
url: string;
|
|
12
|
-
version: string;
|
|
13
|
-
range: string;
|
|
14
|
-
peerDeps?: string[];
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
type NormalizedDependency = {
|
|
18
|
-
name: string;
|
|
19
|
-
} & Dependency;
|
|
20
|
-
|
|
21
|
-
type DependencyMap = {
|
|
22
|
-
dependencies: Record<string, Dependency>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type { MatchResult } from './types';
|
|
26
|
-
|
|
27
|
-
export function moduleResolver(
|
|
28
|
-
url: string,
|
|
29
|
-
microAppContainer: HTMLElement,
|
|
30
|
-
mainAppContainer: HTMLElement,
|
|
31
|
-
): MatchResult | undefined {
|
|
32
|
-
const dependencyMapSelector = 'script[type=dependencymap]';
|
|
33
|
-
|
|
34
|
-
const microAppDependenciesString = microAppContainer.querySelector(dependencyMapSelector)?.innerHTML;
|
|
35
|
-
if (microAppDependenciesString) {
|
|
36
|
-
const { dependencies } = JSON.parse(microAppDependenciesString) as DependencyMap;
|
|
37
|
-
const normalizedDependencies = normalizeDependencies(dependencies);
|
|
38
|
-
const microAppDependency = normalizedDependencies.find((v) => v.url === url);
|
|
39
|
-
|
|
40
|
-
if (microAppDependency) {
|
|
41
|
-
const mainAppDependencyMapString = mainAppContainer.querySelector(dependencyMapSelector)?.innerHTML;
|
|
42
|
-
|
|
43
|
-
if (mainAppDependencyMapString) {
|
|
44
|
-
const mainAppDependencyMap = JSON.parse(mainAppDependencyMapString) as DependencyMap;
|
|
45
|
-
const matchedDeps = (microAppContainer.__matched_deps__ ??= []);
|
|
46
|
-
const matchedDep = findDependency(
|
|
47
|
-
microAppDependency,
|
|
48
|
-
normalizeDependencies(mainAppDependencyMap.dependencies),
|
|
49
|
-
matchedDeps,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
if (matchedDep) {
|
|
53
|
-
matchedDeps.push(matchedDep.name);
|
|
54
|
-
return matchedDep;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function findDependency(
|
|
64
|
-
dependency: NormalizedDependency,
|
|
65
|
-
mainAppDependencies: NormalizedDependency[],
|
|
66
|
-
matchedDependencies: string[],
|
|
67
|
-
): MatchResult | undefined {
|
|
68
|
-
const matched = mainAppDependencies.find(
|
|
69
|
-
(mainAppDependency) =>
|
|
70
|
-
mainAppDependency.name === dependency.name &&
|
|
71
|
-
satisfies(mainAppDependency.version, dependency.range) &&
|
|
72
|
-
// peer dependencies must be cached before
|
|
73
|
-
(dependency.peerDeps || []).every((peerDep) => matchedDependencies.indexOf(peerDep) !== -1),
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
if (matched) {
|
|
77
|
-
return {
|
|
78
|
-
name: matched.name,
|
|
79
|
-
version: matched.version,
|
|
80
|
-
url: matched.url,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function normalizeDependencies(dependencies: DependencyMap['dependencies']): NormalizedDependency[] {
|
|
88
|
-
return Object.keys(dependencies).map((name) => ({
|
|
89
|
-
name,
|
|
90
|
-
...dependencies[name],
|
|
91
|
-
}));
|
|
92
|
-
}
|
package/src/typings.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
declare module 'semver/functions/satisfies' {
|
|
2
|
-
export default function satisfies(version: string, range: string): boolean;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
type Priority = 'high' | 'low' | 'auto';
|
|
6
|
-
|
|
7
|
-
interface HTMLScriptElement {
|
|
8
|
-
fetchPriority?: Priority;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface RequestInit {
|
|
12
|
-
priority?: Priority;
|
|
13
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Kuitos
|
|
3
|
-
* @since 2023-04-26
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
7
|
-
export const { create, defineProperty, getOwnPropertyDescriptor, getOwnPropertyNames, freeze, keys } = Object;
|
|
8
|
-
export const hasOwnProperty = (caller: unknown, p: PropertyKey) => Object.prototype.hasOwnProperty.call(caller, p);
|
|
9
|
-
|
|
10
|
-
export class Deferred<T> {
|
|
11
|
-
promise: Promise<T>;
|
|
12
|
-
|
|
13
|
-
resolve!: (value: T | PromiseLike<T>) => void;
|
|
14
|
-
|
|
15
|
-
reject!: (reason?: unknown) => void;
|
|
16
|
-
|
|
17
|
-
constructor() {
|
|
18
|
-
this.promise = new Promise((resolve, reject) => {
|
|
19
|
-
this.resolve = resolve;
|
|
20
|
-
this.reject = reject;
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getEntireUrl(uri: string, baseURI: string): string {
|
|
26
|
-
const publicPath = new URL(baseURI, window.location.href);
|
|
27
|
-
const entireUrl = new URL(uri, publicPath.toString());
|
|
28
|
-
return entireUrl.toString();
|
|
29
|
-
}
|