@hanzogui/static 2.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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/check-dep-versions.cjs +267 -0
- package/dist/checkDeps.cjs +200 -0
- package/dist/constants.cjs +49 -0
- package/dist/exports.cjs +44 -0
- package/dist/extractor/accessSafe.cjs +46 -0
- package/dist/extractor/babelParse.cjs +54 -0
- package/dist/extractor/buildClassName.cjs +62 -0
- package/dist/extractor/bundle.cjs +185 -0
- package/dist/extractor/bundleConfig.cjs +513 -0
- package/dist/extractor/concatClassName.cjs +80 -0
- package/dist/extractor/createEvaluator.cjs +75 -0
- package/dist/extractor/createExtractor.cjs +1150 -0
- package/dist/extractor/createLogger.cjs +45 -0
- package/dist/extractor/detectModuleFormat.cjs +49 -0
- package/dist/extractor/ensureImportingConcat.cjs +48 -0
- package/dist/extractor/errors.cjs +26 -0
- package/dist/extractor/esbuildAliasPlugin.cjs +44 -0
- package/dist/extractor/esbuildTsconfigPaths.cjs +86 -0
- package/dist/extractor/evaluateAstNode.cjs +83 -0
- package/dist/extractor/extractHelpers.cjs +119 -0
- package/dist/extractor/extractMediaStyle.cjs +128 -0
- package/dist/extractor/extractToClassNames.cjs +321 -0
- package/dist/extractor/extractToNative.cjs +266 -0
- package/dist/extractor/findTopmostFunction.cjs +34 -0
- package/dist/extractor/generatedUid.cjs +47 -0
- package/dist/extractor/getGuiConfigPathFromOptionsConfig.cjs +35 -0
- package/dist/extractor/getPrefixLogs.cjs +29 -0
- package/dist/extractor/getPropValueFromAttributes.cjs +67 -0
- package/dist/extractor/getSourceModule.cjs +64 -0
- package/dist/extractor/getStaticBindingsForScope.cjs +150 -0
- package/dist/extractor/hoistClassNames.cjs +62 -0
- package/dist/extractor/literalToAst.cjs +84 -0
- package/dist/extractor/loadFile.cjs +11 -0
- package/dist/extractor/loadGui.cjs +322 -0
- package/dist/extractor/logLines.cjs +35 -0
- package/dist/extractor/normalizeTernaries.cjs +73 -0
- package/dist/extractor/propsToFontFamilyCache.cjs +38 -0
- package/dist/extractor/regenerateConfig.cjs +150 -0
- package/dist/extractor/removeUnusedHooks.cjs +76 -0
- package/dist/extractor/timer.cjs +43 -0
- package/dist/extractor/validHTMLAttributes.cjs +77 -0
- package/dist/extractor/watchGuiConfig.cjs +58 -0
- package/dist/getPragmaOptions.cjs +58 -0
- package/dist/helpers/memoize.cjs +37 -0
- package/dist/helpers/requireGuiCore.cjs +33 -0
- package/dist/index.cjs +40 -0
- package/dist/registerRequire.cjs +115 -0
- package/dist/server.cjs +75 -0
- package/dist/setup.cjs +0 -0
- package/dist/types.cjs +16 -0
- package/dist/worker.cjs +89 -0
- package/package.json +101 -0
- package/src/check-dep-versions.ts +738 -0
- package/src/checkDeps.ts +371 -0
- package/src/constants.ts +14 -0
- package/src/exports.ts +15 -0
- package/src/extractor/accessSafe.ts +22 -0
- package/src/extractor/babelParse.ts +37 -0
- package/src/extractor/buildClassName.ts +76 -0
- package/src/extractor/bundle.ts +277 -0
- package/src/extractor/bundleConfig.ts +958 -0
- package/src/extractor/concatClassName.ts +105 -0
- package/src/extractor/createEvaluator.ts +82 -0
- package/src/extractor/createExtractor.ts +2665 -0
- package/src/extractor/createLogger.ts +41 -0
- package/src/extractor/detectModuleFormat.ts +42 -0
- package/src/extractor/ensureImportingConcat.ts +36 -0
- package/src/extractor/errors.ts +1 -0
- package/src/extractor/esbuildAliasPlugin.ts +40 -0
- package/src/extractor/esbuildTsconfigPaths.ts +103 -0
- package/src/extractor/evaluateAstNode.ts +136 -0
- package/src/extractor/extractHelpers.ts +211 -0
- package/src/extractor/extractMediaStyle.ts +194 -0
- package/src/extractor/extractToClassNames.ts +631 -0
- package/src/extractor/extractToNative.ts +463 -0
- package/src/extractor/findTopmostFunction.ts +24 -0
- package/src/extractor/generatedUid.ts +41 -0
- package/src/extractor/getGuiConfigPathFromOptionsConfig.ts +24 -0
- package/src/extractor/getPrefixLogs.ts +9 -0
- package/src/extractor/getPropValueFromAttributes.ts +95 -0
- package/src/extractor/getSourceModule.ts +96 -0
- package/src/extractor/getStaticBindingsForScope.ts +237 -0
- package/src/extractor/hoistClassNames.ts +52 -0
- package/src/extractor/literalToAst.ts +85 -0
- package/src/extractor/loadFile.ts +17 -0
- package/src/extractor/loadGui.ts +487 -0
- package/src/extractor/logLines.ts +16 -0
- package/src/extractor/normalizeTernaries.ts +75 -0
- package/src/extractor/propsToFontFamilyCache.ts +18 -0
- package/src/extractor/regenerateConfig.ts +186 -0
- package/src/extractor/removeUnusedHooks.ts +83 -0
- package/src/extractor/timer.ts +25 -0
- package/src/extractor/validHTMLAttributes.ts +52 -0
- package/src/extractor/watchGuiConfig.ts +57 -0
- package/src/getPragmaOptions.ts +57 -0
- package/src/helpers/memoize.ts +24 -0
- package/src/helpers/requireGuiCore.ts +28 -0
- package/src/index.ts +4 -0
- package/src/registerRequire.ts +236 -0
- package/src/server.ts +43 -0
- package/src/setup.ts +0 -0
- package/src/types.ts +109 -0
- package/src/worker.ts +142 -0
- package/types/check-dep-versions.d.ts +37 -0
- package/types/check-dep-versions.d.ts.map +1 -0
- package/types/checkDeps.d.ts +19 -0
- package/types/checkDeps.d.ts.map +1 -0
- package/types/constants.d.ts +6 -0
- package/types/constants.d.ts.map +1 -0
- package/types/exports.d.ts +16 -0
- package/types/exports.d.ts.map +1 -0
- package/types/extractor/accessSafe.d.ts +3 -0
- package/types/extractor/accessSafe.d.ts.map +1 -0
- package/types/extractor/babelParse.d.ts +5 -0
- package/types/extractor/babelParse.d.ts.map +1 -0
- package/types/extractor/buildClassName.d.ts +7 -0
- package/types/extractor/buildClassName.d.ts.map +1 -0
- package/types/extractor/bundle.d.ts +121 -0
- package/types/extractor/bundle.d.ts.map +1 -0
- package/types/extractor/bundleConfig.d.ts +49 -0
- package/types/extractor/bundleConfig.d.ts.map +1 -0
- package/types/extractor/concatClassName.d.ts +8 -0
- package/types/extractor/concatClassName.d.ts.map +1 -0
- package/types/extractor/createEvaluator.d.ts +12 -0
- package/types/extractor/createEvaluator.d.ts.map +1 -0
- package/types/extractor/createExtractor.d.ts +32 -0
- package/types/extractor/createExtractor.d.ts.map +1 -0
- package/types/extractor/createLogger.d.ts +3 -0
- package/types/extractor/createLogger.d.ts.map +1 -0
- package/types/extractor/detectModuleFormat.d.ts +5 -0
- package/types/extractor/detectModuleFormat.d.ts.map +1 -0
- package/types/extractor/ensureImportingConcat.d.ts +4 -0
- package/types/extractor/ensureImportingConcat.d.ts.map +1 -0
- package/types/extractor/errors.d.ts +3 -0
- package/types/extractor/errors.d.ts.map +1 -0
- package/types/extractor/esbuildAliasPlugin.d.ts +18 -0
- package/types/extractor/esbuildAliasPlugin.d.ts.map +1 -0
- package/types/extractor/esbuildTsconfigPaths.d.ts +11 -0
- package/types/extractor/esbuildTsconfigPaths.d.ts.map +1 -0
- package/types/extractor/evaluateAstNode.d.ts +3 -0
- package/types/extractor/evaluateAstNode.d.ts.map +1 -0
- package/types/extractor/extractHelpers.d.ts +28 -0
- package/types/extractor/extractHelpers.d.ts.map +1 -0
- package/types/extractor/extractMediaStyle.d.ts +11 -0
- package/types/extractor/extractMediaStyle.d.ts.map +1 -0
- package/types/extractor/extractToClassNames.d.ts +25 -0
- package/types/extractor/extractToClassNames.d.ts.map +1 -0
- package/types/extractor/extractToNative.d.ts +13 -0
- package/types/extractor/extractToNative.d.ts.map +1 -0
- package/types/extractor/findTopmostFunction.d.ts +4 -0
- package/types/extractor/findTopmostFunction.d.ts.map +1 -0
- package/types/extractor/generatedUid.d.ts +5 -0
- package/types/extractor/generatedUid.d.ts.map +1 -0
- package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts +3 -0
- package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts.map +1 -0
- package/types/extractor/getPrefixLogs.d.ts +3 -0
- package/types/extractor/getPrefixLogs.d.ts.map +1 -0
- package/types/extractor/getPropValueFromAttributes.d.ts +19 -0
- package/types/extractor/getPropValueFromAttributes.d.ts.map +1 -0
- package/types/extractor/getSourceModule.d.ts +16 -0
- package/types/extractor/getSourceModule.d.ts.map +1 -0
- package/types/extractor/getStaticBindingsForScope.d.ts +5 -0
- package/types/extractor/getStaticBindingsForScope.d.ts.map +1 -0
- package/types/extractor/hoistClassNames.d.ts +6 -0
- package/types/extractor/hoistClassNames.d.ts.map +1 -0
- package/types/extractor/literalToAst.d.ts +4 -0
- package/types/extractor/literalToAst.d.ts.map +1 -0
- package/types/extractor/loadFile.d.ts +1 -0
- package/types/extractor/loadFile.d.ts.map +1 -0
- package/types/extractor/loadGui.d.ts +22 -0
- package/types/extractor/loadGui.d.ts.map +1 -0
- package/types/extractor/logLines.d.ts +2 -0
- package/types/extractor/logLines.d.ts.map +1 -0
- package/types/extractor/normalizeTernaries.d.ts +3 -0
- package/types/extractor/normalizeTernaries.d.ts.map +1 -0
- package/types/extractor/propsToFontFamilyCache.d.ts +4 -0
- package/types/extractor/propsToFontFamilyCache.d.ts.map +1 -0
- package/types/extractor/regenerateConfig.d.ts +9 -0
- package/types/extractor/regenerateConfig.d.ts.map +1 -0
- package/types/extractor/removeUnusedHooks.d.ts +3 -0
- package/types/extractor/removeUnusedHooks.d.ts.map +1 -0
- package/types/extractor/timer.d.ts +5 -0
- package/types/extractor/timer.d.ts.map +1 -0
- package/types/extractor/validHTMLAttributes.d.ts +52 -0
- package/types/extractor/validHTMLAttributes.d.ts.map +1 -0
- package/types/extractor/watchGuiConfig.d.ts +5 -0
- package/types/extractor/watchGuiConfig.d.ts.map +1 -0
- package/types/getPragmaOptions.d.ts +8 -0
- package/types/getPragmaOptions.d.ts.map +1 -0
- package/types/helpers/memoize.d.ts +8 -0
- package/types/helpers/memoize.d.ts.map +1 -0
- package/types/helpers/requireGuiCore.d.ts +3 -0
- package/types/helpers/requireGuiCore.d.ts.map +1 -0
- package/types/index.d.ts +4 -0
- package/types/index.d.ts.map +1 -0
- package/types/registerRequire.d.ts +10 -0
- package/types/registerRequire.d.ts.map +1 -0
- package/types/server.d.ts +3 -0
- package/types/server.d.ts.map +1 -0
- package/types/setup.d.ts +1 -0
- package/types/setup.d.ts.map +1 -0
- package/types/types.d.ts +92 -0
- package/types/types.d.ts.map +1 -0
- package/types/worker.d.ts +46 -0
- package/types/worker.d.ts.map +1 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
|
|
3
|
+
export interface SourceModule {
|
|
4
|
+
sourceModule?: string
|
|
5
|
+
imported?: string
|
|
6
|
+
local?: string
|
|
7
|
+
destructured?: boolean
|
|
8
|
+
usesImportSyntax: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getSourceModule(
|
|
12
|
+
itemName: string,
|
|
13
|
+
itemBinding: {
|
|
14
|
+
constant?: boolean
|
|
15
|
+
path: { node: t.Node; parent: any }
|
|
16
|
+
}
|
|
17
|
+
): SourceModule | null {
|
|
18
|
+
// TODO: deal with reassignment
|
|
19
|
+
if (!itemBinding.constant) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let sourceModule: string | undefined
|
|
24
|
+
let imported: string | undefined
|
|
25
|
+
let local: string | undefined
|
|
26
|
+
let destructured: boolean | undefined
|
|
27
|
+
let usesImportSyntax = false
|
|
28
|
+
|
|
29
|
+
const itemNode = itemBinding.path.node
|
|
30
|
+
|
|
31
|
+
if (t.isImportDefaultSpecifier(itemNode) || t.isImportSpecifier(itemNode)) {
|
|
32
|
+
if (t.isImportDeclaration(itemBinding.path.parent)) {
|
|
33
|
+
sourceModule = itemBinding.path.parent.source.value
|
|
34
|
+
local = itemNode.local.name
|
|
35
|
+
usesImportSyntax = true
|
|
36
|
+
if (t.isImportSpecifier(itemNode)) {
|
|
37
|
+
imported = itemNode.imported['name']
|
|
38
|
+
destructured = true
|
|
39
|
+
} else {
|
|
40
|
+
imported = itemNode.local.name
|
|
41
|
+
destructured = false
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} else if (
|
|
45
|
+
t.isVariableDeclarator(itemNode) &&
|
|
46
|
+
itemNode.init != null &&
|
|
47
|
+
t.isCallExpression(itemNode.init) &&
|
|
48
|
+
t.isIdentifier(itemNode.init.callee) &&
|
|
49
|
+
itemNode.init.callee.name === 'require' &&
|
|
50
|
+
itemNode.init.arguments.length === 1
|
|
51
|
+
) {
|
|
52
|
+
const firstArg = itemNode.init.arguments[0]
|
|
53
|
+
if (!t.isStringLiteral(firstArg)) {
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
sourceModule = firstArg.value
|
|
57
|
+
|
|
58
|
+
if (t.isIdentifier(itemNode.id)) {
|
|
59
|
+
local = itemNode.id.name
|
|
60
|
+
imported = itemNode.id.name
|
|
61
|
+
destructured = false
|
|
62
|
+
} else if (t.isObjectPattern(itemNode.id)) {
|
|
63
|
+
for (const objProp of itemNode.id.properties) {
|
|
64
|
+
if (
|
|
65
|
+
t.isObjectProperty(objProp) &&
|
|
66
|
+
t.isIdentifier(objProp.value) &&
|
|
67
|
+
objProp.value.name === itemName
|
|
68
|
+
) {
|
|
69
|
+
local = objProp.value.name
|
|
70
|
+
// @ts-ignore TODO remove this is only an issue on CI
|
|
71
|
+
imported = objProp.key.name
|
|
72
|
+
destructured = true
|
|
73
|
+
break
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!local || !imported) {
|
|
78
|
+
console.error('could not find prop with value `%s`', itemName)
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
console.error('Unhandled id type: %s', itemNode.id.type)
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
destructured,
|
|
91
|
+
imported,
|
|
92
|
+
local,
|
|
93
|
+
sourceModule,
|
|
94
|
+
usesImportSyntax,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process'
|
|
2
|
+
import { fork } from 'node:child_process'
|
|
3
|
+
import { dirname, extname, join, resolve } from 'node:path'
|
|
4
|
+
|
|
5
|
+
import type { Binding, NodePath } from '@babel/traverse'
|
|
6
|
+
import * as t from '@babel/types'
|
|
7
|
+
|
|
8
|
+
import { evaluateAstNode } from './evaluateAstNode'
|
|
9
|
+
import { getSourceModule } from './getSourceModule'
|
|
10
|
+
|
|
11
|
+
// import { fileURLToPath } from 'node:url'
|
|
12
|
+
// // @ts-ignore
|
|
13
|
+
// const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
14
|
+
|
|
15
|
+
const isLocalImport = (path: string) => path.startsWith('.') || path.startsWith('/')
|
|
16
|
+
|
|
17
|
+
function resolveImportPath(sourcePath: string, path: string) {
|
|
18
|
+
const sourceDir = dirname(sourcePath)
|
|
19
|
+
if (isLocalImport(path)) {
|
|
20
|
+
if (extname(path) === '') {
|
|
21
|
+
path += ''
|
|
22
|
+
}
|
|
23
|
+
return resolve(sourceDir, path)
|
|
24
|
+
}
|
|
25
|
+
return path
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const cache = new Map()
|
|
29
|
+
const pending = new Map<string, Promise<any>>()
|
|
30
|
+
|
|
31
|
+
const loadCmd = `${join(__dirname, 'loadFile.js')}`
|
|
32
|
+
|
|
33
|
+
let exited = false
|
|
34
|
+
|
|
35
|
+
let child: ChildProcess | null = null
|
|
36
|
+
|
|
37
|
+
function forkChild() {
|
|
38
|
+
child = fork(loadCmd, [], {
|
|
39
|
+
execArgv: ['-r', 'esbuild-register'],
|
|
40
|
+
detached: false,
|
|
41
|
+
stdio: 'ignore',
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function cleanupBeforeExit() {
|
|
46
|
+
if (exited) return
|
|
47
|
+
if (!child) return
|
|
48
|
+
child.removeAllListeners()
|
|
49
|
+
child.unref()
|
|
50
|
+
child.disconnect()
|
|
51
|
+
child.kill()
|
|
52
|
+
exited = true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
process.once('SIGTERM', cleanupBeforeExit)
|
|
56
|
+
process.once('SIGINT', cleanupBeforeExit)
|
|
57
|
+
process.once('beforeExit', cleanupBeforeExit)
|
|
58
|
+
|
|
59
|
+
function importModule(path: string) {
|
|
60
|
+
if (!child) {
|
|
61
|
+
forkChild()
|
|
62
|
+
}
|
|
63
|
+
if (pending.has(path)) {
|
|
64
|
+
return pending.get(path)
|
|
65
|
+
}
|
|
66
|
+
const promise = new Promise((res, rej) => {
|
|
67
|
+
if (!child) return
|
|
68
|
+
if (cache.size > 2000) {
|
|
69
|
+
cache.clear()
|
|
70
|
+
}
|
|
71
|
+
if (cache.has(path)) {
|
|
72
|
+
return cache.get(path)
|
|
73
|
+
}
|
|
74
|
+
const listener = (msg: any) => {
|
|
75
|
+
if (!child) return
|
|
76
|
+
if (!msg) return
|
|
77
|
+
if (typeof msg !== 'string') return
|
|
78
|
+
if (msg[0] === '-') {
|
|
79
|
+
rej(new Error(msg.slice(1)))
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
child.removeListener('message', listener)
|
|
83
|
+
const val = JSON.parse(msg)
|
|
84
|
+
cache.set(path, val)
|
|
85
|
+
res(val)
|
|
86
|
+
}
|
|
87
|
+
child.once('message', listener)
|
|
88
|
+
child.send(`${path.replace('.js', '')}`)
|
|
89
|
+
}).finally(() => {
|
|
90
|
+
// clean up pending map to prevent memory leak
|
|
91
|
+
pending.delete(path)
|
|
92
|
+
})
|
|
93
|
+
pending.set(path, promise)
|
|
94
|
+
return promise
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function getStaticBindingsForScope(
|
|
98
|
+
scope: NodePath<t.JSXElement>['scope'],
|
|
99
|
+
whitelist: string[] = [],
|
|
100
|
+
sourcePath: string,
|
|
101
|
+
bindingCache: Record<string, string | null>,
|
|
102
|
+
shouldPrintDebug: boolean | 'verbose'
|
|
103
|
+
): Promise<Record<string, any>> {
|
|
104
|
+
const bindings: Record<string, Binding> = scope.getAllBindings() as any
|
|
105
|
+
const ret: Record<string, any> = {}
|
|
106
|
+
|
|
107
|
+
if (shouldPrintDebug) {
|
|
108
|
+
// prettier-ignore
|
|
109
|
+
// console.info(' ', Object.keys(bindings).length, 'variables in scope')
|
|
110
|
+
// .map(x => bindings[x].identifier?.name).join(', ')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// on react native at least it doesnt find some bindings? not sure why
|
|
114
|
+
// lets add in whitelisted imports if they exist
|
|
115
|
+
const program = scope.getProgramParent().block as t.Program
|
|
116
|
+
for (const node of program.body) {
|
|
117
|
+
if (t.isImportDeclaration(node)) {
|
|
118
|
+
const importPath = node.source.value
|
|
119
|
+
if (!node.specifiers.length) continue
|
|
120
|
+
if (!isLocalImport(importPath)) {
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
const moduleName = resolveImportPath(sourcePath, importPath)
|
|
124
|
+
const isOnWhitelist = whitelist.some((test) => moduleName.endsWith(test))
|
|
125
|
+
if (!isOnWhitelist) continue
|
|
126
|
+
try {
|
|
127
|
+
const src = await importModule(moduleName)
|
|
128
|
+
if (!src) continue
|
|
129
|
+
for (const specifier of node.specifiers) {
|
|
130
|
+
if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
|
|
131
|
+
if (typeof src[specifier.imported.name] !== 'undefined') {
|
|
132
|
+
const val = src[specifier.local.name]
|
|
133
|
+
ret[specifier.local.name] = val
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (err: any) {
|
|
138
|
+
if (shouldPrintDebug) {
|
|
139
|
+
console.warn(
|
|
140
|
+
` | Skipping partial evaluation of constant file: ${moduleName} (DEBUG=hanzo-gui for more)`
|
|
141
|
+
)
|
|
142
|
+
} else if (process.env.DEBUG?.startsWith('@hanzo/gui')) {
|
|
143
|
+
console.info(`Error in partial evaluation`, err.message, err.stack)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!bindingCache) {
|
|
150
|
+
throw new Error('BindingCache is a required param')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (const k in bindings) {
|
|
154
|
+
const binding = bindings[k]
|
|
155
|
+
|
|
156
|
+
// check to see if the item is a module
|
|
157
|
+
const sourceModule = getSourceModule(k, binding)
|
|
158
|
+
if (sourceModule) {
|
|
159
|
+
if (!sourceModule.sourceModule) {
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const moduleName = resolveImportPath(sourcePath, sourceModule.sourceModule)
|
|
164
|
+
const isOnWhitelist = whitelist.some((test) => moduleName.endsWith(test))
|
|
165
|
+
|
|
166
|
+
// TODO we could cache this at the file level.. and check if its been touched since
|
|
167
|
+
|
|
168
|
+
if (isOnWhitelist) {
|
|
169
|
+
const src = importModule(moduleName)
|
|
170
|
+
if (!src) {
|
|
171
|
+
console.info(
|
|
172
|
+
` | ⚠️ Missing file ${moduleName} via ${sourcePath} import ${sourceModule.sourceModule}?`
|
|
173
|
+
)
|
|
174
|
+
return {}
|
|
175
|
+
}
|
|
176
|
+
if (sourceModule.destructured) {
|
|
177
|
+
if (sourceModule.imported) {
|
|
178
|
+
ret[k] = src[sourceModule.imported]
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
ret[k] = src
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
continue
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const { parent } = binding.path
|
|
188
|
+
|
|
189
|
+
if (!t.isVariableDeclaration(parent) || parent.kind !== 'const') {
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// pick out the right variable declarator
|
|
194
|
+
const dec = parent.declarations.find((d) => t.isIdentifier(d.id) && d.id.name === k)
|
|
195
|
+
|
|
196
|
+
// if init is not set, there's nothing to evaluate
|
|
197
|
+
// TODO: handle spread syntax
|
|
198
|
+
if (!dec || !dec.init) {
|
|
199
|
+
continue
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// missing start/end will break caching
|
|
203
|
+
if (typeof dec.id.start !== 'number' || typeof dec.id.end !== 'number') {
|
|
204
|
+
console.error('dec.id.start/end is not a number')
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!t.isIdentifier(dec.id)) {
|
|
209
|
+
console.error('dec is not an identifier')
|
|
210
|
+
continue
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const cacheKey = `${dec.id.name}_${dec.id.start}-${dec.id.end}`
|
|
214
|
+
|
|
215
|
+
// retrieve value from cache
|
|
216
|
+
if (Object.hasOwnProperty.call(bindingCache, cacheKey)) {
|
|
217
|
+
ret[k] = bindingCache[cacheKey]
|
|
218
|
+
continue
|
|
219
|
+
}
|
|
220
|
+
// retrieve value from cache
|
|
221
|
+
if (Object.hasOwnProperty.call(bindingCache, cacheKey)) {
|
|
222
|
+
ret[k] = bindingCache[cacheKey]
|
|
223
|
+
continue
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// evaluate
|
|
227
|
+
try {
|
|
228
|
+
ret[k] = evaluateAstNode(dec.init, undefined, shouldPrintDebug)
|
|
229
|
+
bindingCache[cacheKey] = ret[k]
|
|
230
|
+
continue
|
|
231
|
+
} catch {
|
|
232
|
+
// skip
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return ret
|
|
237
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { NodePath } from '@babel/traverse'
|
|
2
|
+
import * as t from '@babel/types'
|
|
3
|
+
|
|
4
|
+
export function hoistClassNames(
|
|
5
|
+
path: NodePath<t.JSXElement>,
|
|
6
|
+
existing: { [key: string]: t.Identifier },
|
|
7
|
+
expr: t.Expression
|
|
8
|
+
) {
|
|
9
|
+
const hoist = hoistClassNames.bind(null, path, existing)
|
|
10
|
+
if (t.isStringLiteral(expr)) {
|
|
11
|
+
if (expr.value.trim() === '') {
|
|
12
|
+
return expr
|
|
13
|
+
}
|
|
14
|
+
if (existing[expr.value]) {
|
|
15
|
+
return existing[expr.value]
|
|
16
|
+
}
|
|
17
|
+
const identifier = replaceStringWithVariable(expr)
|
|
18
|
+
existing[expr.value] = identifier
|
|
19
|
+
return identifier
|
|
20
|
+
}
|
|
21
|
+
if (t.isBinaryExpression(expr)) {
|
|
22
|
+
if (t.isPrivateName(expr.left)) {
|
|
23
|
+
throw new Error(`no private name`)
|
|
24
|
+
}
|
|
25
|
+
return t.binaryExpression(expr.operator, hoist(expr.left), hoist(expr.right))
|
|
26
|
+
}
|
|
27
|
+
if (t.isLogicalExpression(expr)) {
|
|
28
|
+
return t.logicalExpression(expr.operator, hoist(expr.left), hoist(expr.right))
|
|
29
|
+
}
|
|
30
|
+
if (t.isConditionalExpression(expr)) {
|
|
31
|
+
return t.conditionalExpression(
|
|
32
|
+
expr.test,
|
|
33
|
+
hoist(expr.consequent),
|
|
34
|
+
hoist(expr.alternate)
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
return expr
|
|
38
|
+
|
|
39
|
+
function replaceStringWithVariable(str: t.StringLiteral): t.Identifier {
|
|
40
|
+
// hoist outside fn!
|
|
41
|
+
const uid = path.scope.generateUidIdentifier('cn')
|
|
42
|
+
const parent = path.findParent((path) => path.isProgram())
|
|
43
|
+
if (!parent) throw new Error(`no program?`)
|
|
44
|
+
const variable = t.variableDeclaration('const', [
|
|
45
|
+
// adding a space for extra safety
|
|
46
|
+
t.variableDeclarator(uid, t.stringLiteral(` ${str.value}`)),
|
|
47
|
+
])
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
parent.unshiftContainer('body', variable)
|
|
50
|
+
return uid
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
|
|
3
|
+
export function literalToAst(literal: any): t.Expression {
|
|
4
|
+
if (literal === null) {
|
|
5
|
+
return t.nullLiteral()
|
|
6
|
+
}
|
|
7
|
+
switch (typeof literal) {
|
|
8
|
+
case 'function':
|
|
9
|
+
throw new Error('Unsupported')
|
|
10
|
+
case 'number':
|
|
11
|
+
return t.numericLiteral(literal)
|
|
12
|
+
case 'string':
|
|
13
|
+
return t.stringLiteral(literal)
|
|
14
|
+
case 'boolean':
|
|
15
|
+
return t.booleanLiteral(literal)
|
|
16
|
+
case 'undefined':
|
|
17
|
+
return t.unaryExpression('void', t.numericLiteral(0), true)
|
|
18
|
+
default:
|
|
19
|
+
if (Array.isArray(literal)) {
|
|
20
|
+
return t.arrayExpression(literal.map(literalToAst))
|
|
21
|
+
}
|
|
22
|
+
return t.objectExpression(
|
|
23
|
+
Object.keys(literal)
|
|
24
|
+
.filter((k) => {
|
|
25
|
+
return typeof literal[k] !== 'undefined'
|
|
26
|
+
})
|
|
27
|
+
.map((k) => {
|
|
28
|
+
return t.objectProperty(t.stringLiteral(k), literalToAst(literal[k]))
|
|
29
|
+
})
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const easyPeasies = ['BooleanLiteral', 'StringLiteral', 'NumericLiteral']
|
|
35
|
+
|
|
36
|
+
export function astToLiteral(node: any) {
|
|
37
|
+
if (!node) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if (easyPeasies.includes(node.type)) {
|
|
41
|
+
return node.value
|
|
42
|
+
}
|
|
43
|
+
if (node.name === 'undefined' && !node.value) {
|
|
44
|
+
return undefined
|
|
45
|
+
}
|
|
46
|
+
if (t.isNullLiteral(node)) {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
if (t.isObjectExpression(node)) {
|
|
50
|
+
return computeProps(node.properties)
|
|
51
|
+
}
|
|
52
|
+
if (t.isArrayExpression(node)) {
|
|
53
|
+
return node.elements.reduce(
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
(acc, element) => [
|
|
56
|
+
...acc,
|
|
57
|
+
...(element?.type === 'SpreadElement'
|
|
58
|
+
? astToLiteral(element.argument)
|
|
59
|
+
: [astToLiteral(element)]),
|
|
60
|
+
],
|
|
61
|
+
[]
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function computeProps(props) {
|
|
67
|
+
return props.reduce((acc, prop) => {
|
|
68
|
+
if (prop.type === 'SpreadElement') {
|
|
69
|
+
return {
|
|
70
|
+
...acc,
|
|
71
|
+
...astToLiteral(prop.argument),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (prop.type !== 'ObjectMethod') {
|
|
75
|
+
const val = astToLiteral(prop.value)
|
|
76
|
+
if (val !== undefined) {
|
|
77
|
+
return {
|
|
78
|
+
...acc,
|
|
79
|
+
[prop.key.name]: val,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return acc
|
|
84
|
+
}, {})
|
|
85
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
process.on('message', (path) => {
|
|
2
|
+
if (typeof path !== 'string') {
|
|
3
|
+
throw new Error(`Not a string: ${path}`)
|
|
4
|
+
}
|
|
5
|
+
try {
|
|
6
|
+
const out = require(path)
|
|
7
|
+
process.send?.(JSON.stringify(out))
|
|
8
|
+
} catch (err) {
|
|
9
|
+
if (err instanceof Error) {
|
|
10
|
+
process.send?.(`-${err.message}\n${err.stack}`)
|
|
11
|
+
} else {
|
|
12
|
+
process.send?.(`-${err}`)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
setInterval(() => {}, 1000)
|