@sbee/vite-federation 0.0.1

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.
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Dynamic Remote Loading Utility
3
+ *
4
+ * Cho phép host-app tải remote modules khi chạy (runtime) mà **không cần**
5
+ * khai báo trước trong `vite.config.ts`.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { loadRemote, registerRemote, preloadRemote } from '@sbee/vite-federation/runtime'
10
+ *
11
+ * // Cách 1: Load thẳng không cần đăng ký trước
12
+ * const Button = await loadRemote('https://remote.example.com/remoteEntry.js', './Button')
13
+ *
14
+ * // Cách 2: Đăng ký trước rồi load sau
15
+ * registerRemote('my-remote', { url: 'https://remote.example.com/remoteEntry.js' })
16
+ * const Button = await loadRemote('my-remote', './Button')
17
+ *
18
+ * // Cách 3: Preload trước để init sẵn
19
+ * const remote = await preloadRemote('my-remote', { url: 'https://remote.example.com/remoteEntry.js' })
20
+ * const Button = await remote.get('./Button')
21
+ * ```
22
+ */
23
+ export interface RemoteConfig {
24
+ /** URL tới remote entry file (remoteEntry.js) hoặc function trả về URL */
25
+ url: string | (() => Promise<string>);
26
+ /** Định dạng remote: 'esm' (import()) hay 'var' (script tag + window global) */
27
+ format?: 'esm' | 'var';
28
+ /** Hệ thống build của remote: 'vite' (mặc định) hay 'webpack' */
29
+ from?: 'vite' | 'webpack';
30
+ /** Share scope name, mặc định 'default' */
31
+ shareScope?: string;
32
+ }
33
+ export interface RemoteHandle {
34
+ /** Tải một module đã expose từ remote */
35
+ get<T = any>(moduleName: string): Promise<T>;
36
+ /** Init lại share scope cho remote */
37
+ init(shareScope: Record<string, any>): void;
38
+ /** Remote đã được init chưa */
39
+ readonly inited: boolean;
40
+ }
41
+ /** Lấy hoặc khởi tạo global share scope */
42
+ export declare function getShareScope(scopeName?: string): Record<string, any>;
43
+ /** Đăng ký shared packages vào share scope (thường dùng bởi host) */
44
+ export declare function provideShared(scopeName: string, packages: Record<string, Record<string, {
45
+ get: () => Promise<() => any>;
46
+ }>>): void;
47
+ /**
48
+ * Đăng ký một remote để dùng sau này.
49
+ * Hàm này đồng bộ, không tải gì cả — chỉ lưu config.
50
+ */
51
+ export declare function registerRemote(name: string, config: RemoteConfig): void;
52
+ /**
53
+ * Preload & init một remote, trả về handle để gọi `.get()`.
54
+ * Cache lại — gọi nhiều lần với cùng `name` chỉ tải & init một lần,
55
+ * kể cả khi gọi đồng thời (dedup promise in-flight).
56
+ */
57
+ export declare function preloadRemote(name: string, config?: RemoteConfig): Promise<RemoteHandle>;
58
+ /**
59
+ * Tải một module từ remote (có thể chưa đăng ký trước).
60
+ *
61
+ * @param remoteUrlOrName - URL tới remoteEntry.js HOẶC tên đã đăng ký qua `registerRemote()`
62
+ * @param moduleName - Đường dẫn module đã expose, VD: `'./Button'`, `'./App'`
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * // Dùng URL trực tiếp
67
+ * const Button = await loadRemote('https://my-app.com/remoteEntry.js', './Button')
68
+ *
69
+ * // Dùng tên đã đăng ký
70
+ * registerRemote('my-remote', { url: 'https://my-app.com/remoteEntry.js' })
71
+ * const Button = await loadRemote('my-remote', './Button')
72
+ * ```
73
+ */
74
+ export declare function loadRemote<T = any>(remoteUrlOrName: string, moduleName: string, config?: RemoteConfig): Promise<T>;
75
+ /**
76
+ * Tải nhiều module cùng lúc từ một remote.
77
+ */
78
+ export declare function loadRemoteModules<T extends Record<string, string>>(remoteUrlOrName: string, modules: T, config?: RemoteConfig): Promise<{
79
+ [K in keyof T]: any;
80
+ }>;
@@ -0,0 +1,176 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/runtime/index.ts
3
+ var _remoteMap = /* @__PURE__ */ new Map();
4
+ var _remoteConfigMap = /* @__PURE__ */ new Map();
5
+ var _pendingMap = /* @__PURE__ */ new Map();
6
+ /** Lấy hoặc khởi tạo global share scope */
7
+ function getShareScope(scopeName = "default") {
8
+ const g = globalThis;
9
+ g.__federation_shared__ = g.__federation_shared__ || {};
10
+ g.__federation_shared__[scopeName] = g.__federation_shared__[scopeName] || {};
11
+ return g.__federation_shared__[scopeName];
12
+ }
13
+ /** Đăng ký shared packages vào share scope (thường dùng bởi host) */
14
+ function provideShared(scopeName, packages) {
15
+ const scope = getShareScope(scopeName);
16
+ for (const [pkgName, versions] of Object.entries(packages)) {
17
+ scope[pkgName] = scope[pkgName] || {};
18
+ Object.assign(scope[pkgName], versions);
19
+ }
20
+ }
21
+ function resolveUrl(url) {
22
+ return typeof url === "function" ? url() : Promise.resolve(url);
23
+ }
24
+ function unwrapModule(module, from) {
25
+ if (from === "webpack") return Object.prototype.toString.call(module).indexOf("Module") > -1 && module.default ? module.default : module;
26
+ return module?.__esModule || module?.[Symbol.toStringTag] === "Module" ? module.default : module;
27
+ }
28
+ function mergeShareScope(target, source) {
29
+ const merged = Object.assign({}, target, source);
30
+ for (const key of Object.keys(merged)) if (typeof merged[key] === "object" && typeof source[key] === "object") merged[key] = mergeShareScope(merged[key], source[key]);
31
+ return merged;
32
+ }
33
+ /**
34
+ * Đăng ký một remote để dùng sau này.
35
+ * Hàm này đồng bộ, không tải gì cả — chỉ lưu config.
36
+ */
37
+ function registerRemote(name, config) {
38
+ _remoteConfigMap.set(name, config);
39
+ }
40
+ /** Tải + init một remote entry đúng MỘT lần cho mỗi name (dedup promise in-flight). */
41
+ function ensureLoaded(name, cfg, shareScope) {
42
+ const existingEntry = _remoteMap.get(name);
43
+ if (existingEntry?.inited) return Promise.resolve(existingEntry);
44
+ const pending = _pendingMap.get(name);
45
+ if (pending) return pending;
46
+ const tracked = (async () => {
47
+ if (cfg.format === "var") {
48
+ const url = await resolveUrl(cfg.url);
49
+ return await new Promise((resolve, reject) => {
50
+ const finish = (lib) => {
51
+ const wrapped = Object.assign(lib, { inited: false });
52
+ wrapped.init(shareScope);
53
+ wrapped.inited = true;
54
+ resolve(wrapped);
55
+ };
56
+ const existing = window[name];
57
+ if (existing) {
58
+ finish(existing);
59
+ return;
60
+ }
61
+ const script = document.createElement("script");
62
+ script.type = "text/javascript";
63
+ script.onload = () => {
64
+ const lib = window[name];
65
+ if (!lib) return reject(/* @__PURE__ */ new Error(`[mf-runtime] Remote "${name}" không expose global "${name}"`));
66
+ finish(lib);
67
+ };
68
+ script.onerror = () => reject(/* @__PURE__ */ new Error(`[mf-runtime] Không thể tải remote "${name}" từ ${url}`));
69
+ script.src = url;
70
+ document.head.appendChild(script);
71
+ });
72
+ }
73
+ const lib = await import(
74
+ /* @vite-ignore */
75
+ await resolveUrl(cfg.url)
76
+ );
77
+ const wrapped = Object.assign(lib, { inited: false });
78
+ wrapped.init(shareScope);
79
+ wrapped.inited = true;
80
+ return wrapped;
81
+ })().then((entry) => {
82
+ _remoteMap.set(name, entry);
83
+ return entry;
84
+ }).finally(() => {
85
+ _pendingMap.delete(name);
86
+ });
87
+ _pendingMap.set(name, tracked);
88
+ return tracked;
89
+ }
90
+ /**
91
+ * Preload & init một remote, trả về handle để gọi `.get()`.
92
+ * Cache lại — gọi nhiều lần với cùng `name` chỉ tải & init một lần,
93
+ * kể cả khi gọi đồng thời (dedup promise in-flight).
94
+ */
95
+ async function preloadRemote(name, config) {
96
+ const cfg = config ?? _remoteConfigMap.get(name);
97
+ if (!cfg) throw new Error(`[mf-runtime] Remote "${name}" chưa được đăng ký. Gọi registerRemote() trước hoặc truyền config.`);
98
+ const shareScope = getShareScope(cfg.shareScope || "default");
99
+ await ensureLoaded(name, cfg, shareScope);
100
+ return {
101
+ async get(moduleName) {
102
+ const e = _remoteMap.get(name);
103
+ if (!e) throw new Error(`[mf-runtime] Remote "${name}" chưa được load`);
104
+ return unwrapModule((await e.get(moduleName))(), cfg.from);
105
+ },
106
+ init(shareScopeInput) {
107
+ const e = _remoteMap.get(name);
108
+ if (e) {
109
+ const merged = mergeShareScope(shareScope, shareScopeInput);
110
+ e.init(merged);
111
+ }
112
+ },
113
+ get inited() {
114
+ return _remoteMap.get(name)?.inited ?? false;
115
+ }
116
+ };
117
+ }
118
+ /**
119
+ * Phân giải `remoteUrlOrName` thành `{ name, cfg }`:
120
+ * - Nếu là tên đã đăng ký qua `registerRemote()` → dùng config đã lưu (trừ khi truyền `config` override).
121
+ * - Nếu là URL → tạo tên tự động và đăng ký config `{ url }`.
122
+ */
123
+ function resolveRemote(remoteUrlOrName, config) {
124
+ if (_remoteConfigMap.has(remoteUrlOrName)) return {
125
+ name: remoteUrlOrName,
126
+ cfg: config ?? _remoteConfigMap.get(remoteUrlOrName)
127
+ };
128
+ const name = `__dynamic__${remoteUrlOrName}`;
129
+ const cfg = config ?? { url: remoteUrlOrName };
130
+ if (!_remoteConfigMap.has(name)) registerRemote(name, cfg);
131
+ return {
132
+ name,
133
+ cfg
134
+ };
135
+ }
136
+ /**
137
+ * Tải một module từ remote (có thể chưa đăng ký trước).
138
+ *
139
+ * @param remoteUrlOrName - URL tới remoteEntry.js HOẶC tên đã đăng ký qua `registerRemote()`
140
+ * @param moduleName - Đường dẫn module đã expose, VD: `'./Button'`, `'./App'`
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * // Dùng URL trực tiếp
145
+ * const Button = await loadRemote('https://my-app.com/remoteEntry.js', './Button')
146
+ *
147
+ * // Dùng tên đã đăng ký
148
+ * registerRemote('my-remote', { url: 'https://my-app.com/remoteEntry.js' })
149
+ * const Button = await loadRemote('my-remote', './Button')
150
+ * ```
151
+ */
152
+ async function loadRemote(remoteUrlOrName, moduleName, config) {
153
+ const { name, cfg } = resolveRemote(remoteUrlOrName, config);
154
+ return (await preloadRemote(name, cfg)).get(moduleName);
155
+ }
156
+ /**
157
+ * Tải nhiều module cùng lúc từ một remote.
158
+ */
159
+ async function loadRemoteModules(remoteUrlOrName, modules, config) {
160
+ const { name, cfg } = resolveRemote(remoteUrlOrName, config);
161
+ const remote = await preloadRemote(name, cfg);
162
+ const entries = Object.entries(modules);
163
+ const results = await Promise.all(entries.map(([, mod]) => remote.get(mod)));
164
+ const result = {};
165
+ entries.forEach(([key], i) => {
166
+ result[key] = results[i];
167
+ });
168
+ return result;
169
+ }
170
+ //#endregion
171
+ exports.getShareScope = getShareScope;
172
+ exports.loadRemote = loadRemote;
173
+ exports.loadRemoteModules = loadRemoteModules;
174
+ exports.preloadRemote = preloadRemote;
175
+ exports.provideShared = provideShared;
176
+ exports.registerRemote = registerRemote;
@@ -0,0 +1,170 @@
1
+ //#region src/runtime/index.ts
2
+ var _remoteMap = /* @__PURE__ */ new Map();
3
+ var _remoteConfigMap = /* @__PURE__ */ new Map();
4
+ var _pendingMap = /* @__PURE__ */ new Map();
5
+ /** Lấy hoặc khởi tạo global share scope */
6
+ function getShareScope(scopeName = "default") {
7
+ const g = globalThis;
8
+ g.__federation_shared__ = g.__federation_shared__ || {};
9
+ g.__federation_shared__[scopeName] = g.__federation_shared__[scopeName] || {};
10
+ return g.__federation_shared__[scopeName];
11
+ }
12
+ /** Đăng ký shared packages vào share scope (thường dùng bởi host) */
13
+ function provideShared(scopeName, packages) {
14
+ const scope = getShareScope(scopeName);
15
+ for (const [pkgName, versions] of Object.entries(packages)) {
16
+ scope[pkgName] = scope[pkgName] || {};
17
+ Object.assign(scope[pkgName], versions);
18
+ }
19
+ }
20
+ function resolveUrl(url) {
21
+ return typeof url === "function" ? url() : Promise.resolve(url);
22
+ }
23
+ function unwrapModule(module, from) {
24
+ if (from === "webpack") return Object.prototype.toString.call(module).indexOf("Module") > -1 && module.default ? module.default : module;
25
+ return module?.__esModule || module?.[Symbol.toStringTag] === "Module" ? module.default : module;
26
+ }
27
+ function mergeShareScope(target, source) {
28
+ const merged = Object.assign({}, target, source);
29
+ for (const key of Object.keys(merged)) if (typeof merged[key] === "object" && typeof source[key] === "object") merged[key] = mergeShareScope(merged[key], source[key]);
30
+ return merged;
31
+ }
32
+ /**
33
+ * Đăng ký một remote để dùng sau này.
34
+ * Hàm này đồng bộ, không tải gì cả — chỉ lưu config.
35
+ */
36
+ function registerRemote(name, config) {
37
+ _remoteConfigMap.set(name, config);
38
+ }
39
+ /** Tải + init một remote entry đúng MỘT lần cho mỗi name (dedup promise in-flight). */
40
+ function ensureLoaded(name, cfg, shareScope) {
41
+ const existingEntry = _remoteMap.get(name);
42
+ if (existingEntry?.inited) return Promise.resolve(existingEntry);
43
+ const pending = _pendingMap.get(name);
44
+ if (pending) return pending;
45
+ const tracked = (async () => {
46
+ if (cfg.format === "var") {
47
+ const url = await resolveUrl(cfg.url);
48
+ return await new Promise((resolve, reject) => {
49
+ const finish = (lib) => {
50
+ const wrapped = Object.assign(lib, { inited: false });
51
+ wrapped.init(shareScope);
52
+ wrapped.inited = true;
53
+ resolve(wrapped);
54
+ };
55
+ const existing = window[name];
56
+ if (existing) {
57
+ finish(existing);
58
+ return;
59
+ }
60
+ const script = document.createElement("script");
61
+ script.type = "text/javascript";
62
+ script.onload = () => {
63
+ const lib = window[name];
64
+ if (!lib) return reject(/* @__PURE__ */ new Error(`[mf-runtime] Remote "${name}" không expose global "${name}"`));
65
+ finish(lib);
66
+ };
67
+ script.onerror = () => reject(/* @__PURE__ */ new Error(`[mf-runtime] Không thể tải remote "${name}" từ ${url}`));
68
+ script.src = url;
69
+ document.head.appendChild(script);
70
+ });
71
+ }
72
+ const lib = await import(
73
+ /* @vite-ignore */
74
+ await resolveUrl(cfg.url)
75
+ );
76
+ const wrapped = Object.assign(lib, { inited: false });
77
+ wrapped.init(shareScope);
78
+ wrapped.inited = true;
79
+ return wrapped;
80
+ })().then((entry) => {
81
+ _remoteMap.set(name, entry);
82
+ return entry;
83
+ }).finally(() => {
84
+ _pendingMap.delete(name);
85
+ });
86
+ _pendingMap.set(name, tracked);
87
+ return tracked;
88
+ }
89
+ /**
90
+ * Preload & init một remote, trả về handle để gọi `.get()`.
91
+ * Cache lại — gọi nhiều lần với cùng `name` chỉ tải & init một lần,
92
+ * kể cả khi gọi đồng thời (dedup promise in-flight).
93
+ */
94
+ async function preloadRemote(name, config) {
95
+ const cfg = config ?? _remoteConfigMap.get(name);
96
+ if (!cfg) throw new Error(`[mf-runtime] Remote "${name}" chưa được đăng ký. Gọi registerRemote() trước hoặc truyền config.`);
97
+ const shareScope = getShareScope(cfg.shareScope || "default");
98
+ await ensureLoaded(name, cfg, shareScope);
99
+ return {
100
+ async get(moduleName) {
101
+ const e = _remoteMap.get(name);
102
+ if (!e) throw new Error(`[mf-runtime] Remote "${name}" chưa được load`);
103
+ return unwrapModule((await e.get(moduleName))(), cfg.from);
104
+ },
105
+ init(shareScopeInput) {
106
+ const e = _remoteMap.get(name);
107
+ if (e) {
108
+ const merged = mergeShareScope(shareScope, shareScopeInput);
109
+ e.init(merged);
110
+ }
111
+ },
112
+ get inited() {
113
+ return _remoteMap.get(name)?.inited ?? false;
114
+ }
115
+ };
116
+ }
117
+ /**
118
+ * Phân giải `remoteUrlOrName` thành `{ name, cfg }`:
119
+ * - Nếu là tên đã đăng ký qua `registerRemote()` → dùng config đã lưu (trừ khi truyền `config` override).
120
+ * - Nếu là URL → tạo tên tự động và đăng ký config `{ url }`.
121
+ */
122
+ function resolveRemote(remoteUrlOrName, config) {
123
+ if (_remoteConfigMap.has(remoteUrlOrName)) return {
124
+ name: remoteUrlOrName,
125
+ cfg: config ?? _remoteConfigMap.get(remoteUrlOrName)
126
+ };
127
+ const name = `__dynamic__${remoteUrlOrName}`;
128
+ const cfg = config ?? { url: remoteUrlOrName };
129
+ if (!_remoteConfigMap.has(name)) registerRemote(name, cfg);
130
+ return {
131
+ name,
132
+ cfg
133
+ };
134
+ }
135
+ /**
136
+ * Tải một module từ remote (có thể chưa đăng ký trước).
137
+ *
138
+ * @param remoteUrlOrName - URL tới remoteEntry.js HOẶC tên đã đăng ký qua `registerRemote()`
139
+ * @param moduleName - Đường dẫn module đã expose, VD: `'./Button'`, `'./App'`
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * // Dùng URL trực tiếp
144
+ * const Button = await loadRemote('https://my-app.com/remoteEntry.js', './Button')
145
+ *
146
+ * // Dùng tên đã đăng ký
147
+ * registerRemote('my-remote', { url: 'https://my-app.com/remoteEntry.js' })
148
+ * const Button = await loadRemote('my-remote', './Button')
149
+ * ```
150
+ */
151
+ async function loadRemote(remoteUrlOrName, moduleName, config) {
152
+ const { name, cfg } = resolveRemote(remoteUrlOrName, config);
153
+ return (await preloadRemote(name, cfg)).get(moduleName);
154
+ }
155
+ /**
156
+ * Tải nhiều module cùng lúc từ một remote.
157
+ */
158
+ async function loadRemoteModules(remoteUrlOrName, modules, config) {
159
+ const { name, cfg } = resolveRemote(remoteUrlOrName, config);
160
+ const remote = await preloadRemote(name, cfg);
161
+ const entries = Object.entries(modules);
162
+ const results = await Promise.all(entries.map(([, mod]) => remote.get(mod)));
163
+ const result = {};
164
+ entries.forEach(([key], i) => {
165
+ result[key] = results[i];
166
+ });
167
+ return result;
168
+ }
169
+ //#endregion
170
+ export { getShareScope, loadRemote, loadRemoteModules, preloadRemote, provideShared, registerRemote };
@@ -0,0 +1,223 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/utils/semver/constants.ts
3
+ var buildIdentifier = "[0-9A-Za-z-]+";
4
+ var build = `(?:\\+(${buildIdentifier}(?:\\.${buildIdentifier})*))`;
5
+ var numericIdentifier = "0|[1-9]\\d*";
6
+ var numericIdentifierLoose = "[0-9]+";
7
+ var nonNumericIdentifier = "\\d*[a-zA-Z-][a-zA-Z0-9-]*";
8
+ var preReleaseIdentifierLoose = `(?:${numericIdentifierLoose}|${nonNumericIdentifier})`;
9
+ var preReleaseLoose = `(?:-?(${preReleaseIdentifierLoose}(?:\\.${preReleaseIdentifierLoose})*))`;
10
+ var preReleaseIdentifier = `(?:${numericIdentifier}|${nonNumericIdentifier})`;
11
+ var preRelease = `(?:-(${preReleaseIdentifier}(?:\\.${preReleaseIdentifier})*))`;
12
+ var xRangeIdentifier = `${numericIdentifier}|x|X|\\*`;
13
+ var xRangePlain = `[v=\\s]*(${xRangeIdentifier})(?:\\.(${xRangeIdentifier})(?:\\.(${xRangeIdentifier})(?:${preRelease})?${build}?)?)?`;
14
+ var hyphenRange = new RegExp(`^\\s*(${xRangePlain})\\s+-\\s+(${xRangePlain})\\s*$`);
15
+ var loosePlain = `[v=\\s]*${`(${numericIdentifierLoose})\\.(${numericIdentifierLoose})\\.(${numericIdentifierLoose})`}${preReleaseLoose}?${build}?`;
16
+ var gtlt = "((?:<|>)?=?)";
17
+ var comparatorTrim = new RegExp(`(\\s*)${gtlt}\\s*(${loosePlain}|${xRangePlain})`);
18
+ var loneTilde = "(?:~>?)";
19
+ var tildeTrim = new RegExp(`(\\s*)${loneTilde}\\s+`);
20
+ var loneCaret = "(?:\\^)";
21
+ var caretTrim = new RegExp(`(\\s*)${loneCaret}\\s+`);
22
+ var star = /* @__PURE__ */ new RegExp("(<|>)?=?\\s*\\*");
23
+ var caret = new RegExp(`^${loneCaret}${xRangePlain}$`);
24
+ var fullPlain = `v?${`(${numericIdentifier})\\.(${numericIdentifier})\\.(${numericIdentifier})`}${preRelease}?${build}?`;
25
+ var tilde = new RegExp(`^${loneTilde}${xRangePlain}$`);
26
+ var xRange = new RegExp(`^${gtlt}\\s*${xRangePlain}$`);
27
+ var comparator = new RegExp(`^${gtlt}\\s*(${fullPlain})$|^$`);
28
+ var gte0 = /* @__PURE__ */ new RegExp("^\\s*>=\\s*0.0.0\\s*$");
29
+ //#endregion
30
+ //#region src/utils/semver/utils.ts
31
+ function isXVersion(version) {
32
+ return !version || version.toLowerCase() === "x" || version === "*";
33
+ }
34
+ function pipe(...fns) {
35
+ return (x) => fns.reduce((v, f) => f(v), x);
36
+ }
37
+ function extractComparator(comparatorString) {
38
+ return comparatorString.match(comparator);
39
+ }
40
+ function combineVersion(major, minor, patch, preRelease) {
41
+ const mainVersion = `${major}.${minor}.${patch}`;
42
+ if (preRelease) return `${mainVersion}-${preRelease}`;
43
+ return mainVersion;
44
+ }
45
+ //#endregion
46
+ //#region src/utils/semver/parser.ts
47
+ function parseHyphen(range) {
48
+ return range.replace(hyphenRange, (_range, from, fromMajor, fromMinor, fromPatch, _fromPreRelease, _fromBuild, to, toMajor, toMinor, toPatch, toPreRelease) => {
49
+ if (isXVersion(fromMajor)) from = "";
50
+ else if (isXVersion(fromMinor)) from = `>=${fromMajor}.0.0`;
51
+ else if (isXVersion(fromPatch)) from = `>=${fromMajor}.${fromMinor}.0`;
52
+ else from = `>=${from}`;
53
+ if (isXVersion(toMajor)) to = "";
54
+ else if (isXVersion(toMinor)) to = `<${+toMajor + 1}.0.0-0`;
55
+ else if (isXVersion(toPatch)) to = `<${toMajor}.${+toMinor + 1}.0-0`;
56
+ else if (toPreRelease) to = `<=${toMajor}.${toMinor}.${toPatch}-${toPreRelease}`;
57
+ else to = `<=${to}`;
58
+ return `${from} ${to}`.trim();
59
+ });
60
+ }
61
+ function parseComparatorTrim(range) {
62
+ return range.replace(comparatorTrim, "$1$2$3");
63
+ }
64
+ function parseTildeTrim(range) {
65
+ return range.replace(tildeTrim, "$1~");
66
+ }
67
+ function parseCaretTrim(range) {
68
+ return range.replace(caretTrim, "$1^");
69
+ }
70
+ function parseCarets(range) {
71
+ return range.trim().split(/\s+/).map((rangeVersion) => {
72
+ return rangeVersion.replace(caret, (_, major, minor, patch, preRelease) => {
73
+ if (isXVersion(major)) return "";
74
+ else if (isXVersion(minor)) return `>=${major}.0.0 <${+major + 1}.0.0-0`;
75
+ else if (isXVersion(patch)) if (major === "0") return `>=${major}.${minor}.0 <${major}.${+minor + 1}.0-0`;
76
+ else return `>=${major}.${minor}.0 <${+major + 1}.0.0-0`;
77
+ else if (preRelease) if (major === "0") if (minor === "0") return `>=${major}.${minor}.${patch}-${preRelease} <${major}.${minor}.${+patch + 1}-0`;
78
+ else return `>=${major}.${minor}.${patch}-${preRelease} <${major}.${+minor + 1}.0-0`;
79
+ else return `>=${major}.${minor}.${patch}-${preRelease} <${+major + 1}.0.0-0`;
80
+ else {
81
+ if (major === "0") if (minor === "0") return `>=${major}.${minor}.${patch} <${major}.${minor}.${+patch + 1}-0`;
82
+ else return `>=${major}.${minor}.${patch} <${major}.${+minor + 1}.0-0`;
83
+ return `>=${major}.${minor}.${patch} <${+major + 1}.0.0-0`;
84
+ }
85
+ });
86
+ }).join(" ");
87
+ }
88
+ function parseTildes(range) {
89
+ return range.trim().split(/\s+/).map((rangeVersion) => {
90
+ return rangeVersion.replace(tilde, (_, major, minor, patch, preRelease) => {
91
+ if (isXVersion(major)) return "";
92
+ else if (isXVersion(minor)) return `>=${major}.0.0 <${+major + 1}.0.0-0`;
93
+ else if (isXVersion(patch)) return `>=${major}.${minor}.0 <${major}.${+minor + 1}.0-0`;
94
+ else if (preRelease) return `>=${major}.${minor}.${patch}-${preRelease} <${major}.${+minor + 1}.0-0`;
95
+ return `>=${major}.${minor}.${patch} <${major}.${+minor + 1}.0-0`;
96
+ });
97
+ }).join(" ");
98
+ }
99
+ function parseXRanges(range) {
100
+ return range.split(/\s+/).map((rangeVersion) => {
101
+ return rangeVersion.trim().replace(xRange, (ret, gtlt, major, minor, patch, preRelease) => {
102
+ const isXMajor = isXVersion(major);
103
+ const isXMinor = isXMajor || isXVersion(minor);
104
+ const isXPatch = isXMinor || isXVersion(patch);
105
+ if (gtlt === "=" && isXPatch) gtlt = "";
106
+ preRelease = "";
107
+ if (isXMajor) if (gtlt === ">" || gtlt === "<") return "<0.0.0-0";
108
+ else return "*";
109
+ else if (gtlt && isXPatch) {
110
+ if (isXMinor) minor = 0;
111
+ patch = 0;
112
+ if (gtlt === ">") {
113
+ gtlt = ">=";
114
+ if (isXMinor) {
115
+ major = +major + 1;
116
+ minor = 0;
117
+ patch = 0;
118
+ } else {
119
+ minor = +minor + 1;
120
+ patch = 0;
121
+ }
122
+ } else if (gtlt === "<=") {
123
+ gtlt = "<";
124
+ if (isXMinor) major = +major + 1;
125
+ else minor = +minor + 1;
126
+ }
127
+ if (gtlt === "<") preRelease = "-0";
128
+ return `${gtlt + major}.${minor}.${patch}${preRelease}`;
129
+ } else if (isXMinor) return `>=${major}.0.0${preRelease} <${+major + 1}.0.0-0`;
130
+ else if (isXPatch) return `>=${major}.${minor}.0${preRelease} <${major}.${+minor + 1}.0-0`;
131
+ return ret;
132
+ });
133
+ }).join(" ");
134
+ }
135
+ function parseStar(range) {
136
+ return range.trim().replace(star, "");
137
+ }
138
+ function parseGTE0(comparatorString) {
139
+ return comparatorString.trim().replace(gte0, "");
140
+ }
141
+ //#endregion
142
+ //#region src/utils/semver/compare.ts
143
+ function compareAtom(rangeAtom, versionAtom) {
144
+ rangeAtom = +rangeAtom || rangeAtom;
145
+ versionAtom = +versionAtom || versionAtom;
146
+ if (rangeAtom > versionAtom) return 1;
147
+ if (rangeAtom === versionAtom) return 0;
148
+ return -1;
149
+ }
150
+ function comparePreRelease(rangeAtom, versionAtom) {
151
+ const { preRelease: rangePreRelease } = rangeAtom;
152
+ const { preRelease: versionPreRelease } = versionAtom;
153
+ if (rangePreRelease === void 0 && !!versionPreRelease) return 1;
154
+ if (!!rangePreRelease && versionPreRelease === void 0) return -1;
155
+ if (rangePreRelease === void 0 && versionPreRelease === void 0) return 0;
156
+ for (let i = 0, n = rangePreRelease.length; i <= n; i++) {
157
+ const rangeElement = rangePreRelease[i];
158
+ const versionElement = versionPreRelease[i];
159
+ if (rangeElement === versionElement) continue;
160
+ if (rangeElement === void 0 && versionElement === void 0) return 0;
161
+ if (!rangeElement) return 1;
162
+ if (!versionElement) return -1;
163
+ return compareAtom(rangeElement, versionElement);
164
+ }
165
+ return 0;
166
+ }
167
+ function compareVersion(rangeAtom, versionAtom) {
168
+ return compareAtom(rangeAtom.major, versionAtom.major) || compareAtom(rangeAtom.minor, versionAtom.minor) || compareAtom(rangeAtom.patch, versionAtom.patch) || comparePreRelease(rangeAtom, versionAtom);
169
+ }
170
+ function eq(rangeAtom, versionAtom) {
171
+ return rangeAtom.version === versionAtom.version;
172
+ }
173
+ function compare(rangeAtom, versionAtom) {
174
+ switch (rangeAtom.operator) {
175
+ case "":
176
+ case "=": return eq(rangeAtom, versionAtom);
177
+ case ">": return compareVersion(rangeAtom, versionAtom) < 0;
178
+ case ">=": return eq(rangeAtom, versionAtom) || compareVersion(rangeAtom, versionAtom) < 0;
179
+ case "<": return compareVersion(rangeAtom, versionAtom) > 0;
180
+ case "<=": return eq(rangeAtom, versionAtom) || compareVersion(rangeAtom, versionAtom) > 0;
181
+ case void 0: return true;
182
+ default: return false;
183
+ }
184
+ }
185
+ //#endregion
186
+ //#region src/utils/semver/satisfy.ts
187
+ function parseComparatorString(range) {
188
+ return pipe(parseCarets, parseTildes, parseXRanges, parseStar)(range);
189
+ }
190
+ function parseRange(range) {
191
+ return pipe(parseHyphen, parseComparatorTrim, parseTildeTrim, parseCaretTrim)(range.trim()).split(/\s+/).join(" ");
192
+ }
193
+ function satisfy(version, range) {
194
+ if (!version) return false;
195
+ const comparators = parseRange(range).split(" ").map((rangeVersion) => parseComparatorString(rangeVersion)).join(" ").split(/\s+/).map((comparator) => parseGTE0(comparator));
196
+ const extractedVersion = extractComparator(version);
197
+ if (!extractedVersion) return false;
198
+ const [, versionOperator, , versionMajor, versionMinor, versionPatch, versionPreRelease] = extractedVersion;
199
+ const versionAtom = {
200
+ operator: versionOperator,
201
+ version: combineVersion(versionMajor, versionMinor, versionPatch, versionPreRelease),
202
+ major: versionMajor,
203
+ minor: versionMinor,
204
+ patch: versionPatch,
205
+ preRelease: versionPreRelease?.split(".")
206
+ };
207
+ for (const comparator of comparators) {
208
+ const extractedComparator = extractComparator(comparator);
209
+ if (!extractedComparator) return false;
210
+ const [, rangeOperator, , rangeMajor, rangeMinor, rangePatch, rangePreRelease] = extractedComparator;
211
+ if (!compare({
212
+ operator: rangeOperator,
213
+ version: combineVersion(rangeMajor, rangeMinor, rangePatch, rangePreRelease),
214
+ major: rangeMajor,
215
+ minor: rangeMinor,
216
+ patch: rangePatch,
217
+ preRelease: rangePreRelease?.split(".")
218
+ }, versionAtom)) return false;
219
+ }
220
+ return true;
221
+ }
222
+ //#endregion
223
+ exports.satisfy = satisfy;