Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b1593d4

Browse files
committed
feat(eval): new package
1 parent e607a7d commit b1593d4

File tree

8 files changed

+449
-9
lines changed

8 files changed

+449
-9
lines changed

packages/eval/package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@unrteljs/eval",
3+
"type": "module",
4+
"version": "0.0.1",
5+
"description": "Evaluate modules",
6+
"author": {
7+
"name": "UnRTEL.js Team & Contributors",
8+
"email": "[email protected]",
9+
"url": "https://github.com/unrteljs"
10+
},
11+
"license": "MIT",
12+
"homepage": "https://github.com/unrteljs/unrtel",
13+
"repository": {
14+
"type": "git",
15+
"url": "git+https://github.com/unrteljs/unrtel.git",
16+
"directory": "packages/eval"
17+
},
18+
"bugs": "https://github.com/unrteljs/unrtel/issues",
19+
"exports": {
20+
".": {
21+
"types": "./dist/index.d.ts",
22+
"import": "./dist/index.mjs",
23+
"node": "./dist/node.mjs",
24+
"browser": "./dist/browser.mjs"
25+
}
26+
},
27+
"files": [
28+
"README.md",
29+
"dist",
30+
"package.json"
31+
],
32+
"scripts": {
33+
"dev": "unbuild",
34+
"stub": "unbuild",
35+
"build": "unbuild",
36+
"typecheck": "tsc --noEmit"
37+
},
38+
"dependencies": {
39+
"error-stack-parser": "^2.1.4",
40+
"sucrase": "^3.35.0"
41+
}
42+
}

packages/eval/src/browser.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L5
2+
3+
import { AsyncFunction } from './utils/helper'
4+
import { getImportBase } from './utils/import-base'
5+
import { exportDefaultRegex, exportRegex, importAsRegex, importDefaultRegex, importObjectRegex, importRegex } from './utils/regexp'
6+
7+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L7-L9
8+
const modulesCache = new Map<string, Promise<unknown> | unknown>()
9+
10+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L26
11+
// eslint-disable-next-line no-new-func
12+
const nativeImport = new Function('a', 'return import(a);')
13+
14+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L31-L33
15+
async function fetchAndImportAnyModuleWithCDNCapabilities(name: string) {
16+
if (name.endsWith('.json')) {
17+
const response = await fetch(getImportBase() + name)
18+
const json = await response.json()
19+
20+
return { default: json }
21+
}
22+
23+
return nativeImport(getImportBase() + name)
24+
}
25+
26+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L27-L37
27+
// bypass vite interop
28+
async function dynamicImportAnyModule(name: string): Promise<any> {
29+
if (modulesCache.has(name))
30+
return modulesCache.get(name)
31+
32+
try {
33+
const module = await fetchAndImportAnyModuleWithCDNCapabilities(name)
34+
modulesCache.set(name, module)
35+
36+
return module
37+
}
38+
catch (error) {
39+
console.error(`Failed to import module ${name} from CDN`, error)
40+
}
41+
}
42+
43+
// https://github.com/unocss/unocss/blob/main/packages/shared-docs/src/config.ts
44+
export async function evaluateAnyModule<T>(configCode: string): Promise<T | undefined> {
45+
const transformedCode = configCode
46+
.replace(importObjectRegex, (_match, p1, _p2, p3) => {
47+
// Replace `as` with `:` within the destructuring assignment
48+
const transformedP1 = p1.replace(importAsRegex, '$1: $2')
49+
return `const {${transformedP1}} = await __import("${p3}");`
50+
})
51+
.replace(importDefaultRegex, 'const $1 = (await __import("$3")).default;')
52+
.replace(exportDefaultRegex, 'return ')
53+
.replace(importRegex, '__import(')
54+
.replace(exportRegex, 'return function ')
55+
56+
const wrappedDynamicImport = new AsyncFunction('__import', transformedCode)
57+
return await wrappedDynamicImport(dynamicImportAnyModule)
58+
}

packages/eval/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './browser'
2+
export * from './utils/import-base'

packages/eval/src/node.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// https://github.com/nolebase/obsidian-plugin-vue/blob/main/src/import.ts
2+
3+
import { createRequire } from 'node:module'
4+
5+
import { AsyncFunction } from './utils/helper'
6+
import { getImportBase, setImportBase } from './utils/import-base'
7+
import { exportDefaultRegex, exportRegex, importAsRegex, importDefaultRegex, importObjectRegex, importRegex } from './utils/regexp'
8+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L31-L33
9+
async function wrappedImport(name: string, basePath?: string) {
10+
const require = createRequire(basePath ?? import.meta.dirname)
11+
return require(name)
12+
}
13+
14+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L27-L37
15+
// bypass vite interop
16+
async function dynamicImportAnyModule(name: string, basePath?: string): Promise<any> {
17+
try {
18+
const module = await wrappedImport(name, basePath)
19+
20+
if (module && module.__esModule) {
21+
const finalModule = module['module.exports'] || module
22+
return finalModule
23+
}
24+
25+
return module
26+
}
27+
catch (error) {
28+
console.error(`Failed to import module ${name}`, error)
29+
}
30+
}
31+
32+
// https://github.com/unocss/unocss/blob/main/packages/shared-docs/src/config.ts
33+
export async function evaluateAnyModule<T>(configCode: string, basePath?: string): Promise<T | undefined> {
34+
const transformedCode = configCode
35+
.replace(importObjectRegex, (_match, p1, _p2, p3) => {
36+
// Replace `as` with `:` within the destructuring assignment
37+
const transformedP1 = p1.replace(importAsRegex, '$1: $2')
38+
return `const {${transformedP1}} = await __import("${p3}");`
39+
})
40+
.replace(importDefaultRegex, 'const $1 = (await __import("$3")).default;')
41+
.replace(exportDefaultRegex, 'return ')
42+
.replace(importRegex, '__import(')
43+
.replace(exportRegex, 'return function ')
44+
45+
const wrappedDynamicImport = new AsyncFunction('__import', transformedCode)
46+
return await wrappedDynamicImport(name => dynamicImportAnyModule(name, basePath))
47+
}
48+
export {
49+
getImportBase,
50+
setImportBase,
51+
}

packages/eval/src/utils/helper.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L5
2+
3+
export const AsyncFunction = Object.getPrototypeOf(async () => { }).constructor
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
let importBase = 'https://esm.sh/'
2+
3+
export function setImportBase(base: string) {
4+
importBase = base
5+
}
6+
7+
export function getImportBase() {
8+
return importBase
9+
}

packages/eval/src/utils/regexp.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// https://github.com/unocss/unocss/blob/6d94efc56b0c966f25f46d8988b3fd30ebc189aa/packages/shared-docs/src/config.ts#L5
2+
3+
// https://github.com/unocss/unocss/blob/main/packages/shared-docs/src/config.ts
4+
export const importObjectRegex = /import\s*\{([\s\S]*?)\}\s*from\s*(['"])([\w@/.:-]+)\2/g
5+
export const importDefaultRegex = /import\s(.*?)\sfrom\s*(['"])([\w@/.:-]+)\2/g
6+
export const exportDefaultRegex = /export default /
7+
export const exportRegex = /export\s(.*?)\s/g
8+
export const importRegex = /\bimport\s*\(/g
9+
10+
// New regex to handle `as` to `:` transformation
11+
export const importAsRegex = /(\w+)\s+as\s+(\w+)/g

0 commit comments

Comments
 (0)