@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.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/check-dep-versions.cjs +267 -0
  4. package/dist/checkDeps.cjs +200 -0
  5. package/dist/constants.cjs +49 -0
  6. package/dist/exports.cjs +44 -0
  7. package/dist/extractor/accessSafe.cjs +46 -0
  8. package/dist/extractor/babelParse.cjs +54 -0
  9. package/dist/extractor/buildClassName.cjs +62 -0
  10. package/dist/extractor/bundle.cjs +185 -0
  11. package/dist/extractor/bundleConfig.cjs +513 -0
  12. package/dist/extractor/concatClassName.cjs +80 -0
  13. package/dist/extractor/createEvaluator.cjs +75 -0
  14. package/dist/extractor/createExtractor.cjs +1150 -0
  15. package/dist/extractor/createLogger.cjs +45 -0
  16. package/dist/extractor/detectModuleFormat.cjs +49 -0
  17. package/dist/extractor/ensureImportingConcat.cjs +48 -0
  18. package/dist/extractor/errors.cjs +26 -0
  19. package/dist/extractor/esbuildAliasPlugin.cjs +44 -0
  20. package/dist/extractor/esbuildTsconfigPaths.cjs +86 -0
  21. package/dist/extractor/evaluateAstNode.cjs +83 -0
  22. package/dist/extractor/extractHelpers.cjs +119 -0
  23. package/dist/extractor/extractMediaStyle.cjs +128 -0
  24. package/dist/extractor/extractToClassNames.cjs +321 -0
  25. package/dist/extractor/extractToNative.cjs +266 -0
  26. package/dist/extractor/findTopmostFunction.cjs +34 -0
  27. package/dist/extractor/generatedUid.cjs +47 -0
  28. package/dist/extractor/getGuiConfigPathFromOptionsConfig.cjs +35 -0
  29. package/dist/extractor/getPrefixLogs.cjs +29 -0
  30. package/dist/extractor/getPropValueFromAttributes.cjs +67 -0
  31. package/dist/extractor/getSourceModule.cjs +64 -0
  32. package/dist/extractor/getStaticBindingsForScope.cjs +150 -0
  33. package/dist/extractor/hoistClassNames.cjs +62 -0
  34. package/dist/extractor/literalToAst.cjs +84 -0
  35. package/dist/extractor/loadFile.cjs +11 -0
  36. package/dist/extractor/loadGui.cjs +322 -0
  37. package/dist/extractor/logLines.cjs +35 -0
  38. package/dist/extractor/normalizeTernaries.cjs +73 -0
  39. package/dist/extractor/propsToFontFamilyCache.cjs +38 -0
  40. package/dist/extractor/regenerateConfig.cjs +150 -0
  41. package/dist/extractor/removeUnusedHooks.cjs +76 -0
  42. package/dist/extractor/timer.cjs +43 -0
  43. package/dist/extractor/validHTMLAttributes.cjs +77 -0
  44. package/dist/extractor/watchGuiConfig.cjs +58 -0
  45. package/dist/getPragmaOptions.cjs +58 -0
  46. package/dist/helpers/memoize.cjs +37 -0
  47. package/dist/helpers/requireGuiCore.cjs +33 -0
  48. package/dist/index.cjs +40 -0
  49. package/dist/registerRequire.cjs +115 -0
  50. package/dist/server.cjs +75 -0
  51. package/dist/setup.cjs +0 -0
  52. package/dist/types.cjs +16 -0
  53. package/dist/worker.cjs +89 -0
  54. package/package.json +101 -0
  55. package/src/check-dep-versions.ts +738 -0
  56. package/src/checkDeps.ts +371 -0
  57. package/src/constants.ts +14 -0
  58. package/src/exports.ts +15 -0
  59. package/src/extractor/accessSafe.ts +22 -0
  60. package/src/extractor/babelParse.ts +37 -0
  61. package/src/extractor/buildClassName.ts +76 -0
  62. package/src/extractor/bundle.ts +277 -0
  63. package/src/extractor/bundleConfig.ts +958 -0
  64. package/src/extractor/concatClassName.ts +105 -0
  65. package/src/extractor/createEvaluator.ts +82 -0
  66. package/src/extractor/createExtractor.ts +2665 -0
  67. package/src/extractor/createLogger.ts +41 -0
  68. package/src/extractor/detectModuleFormat.ts +42 -0
  69. package/src/extractor/ensureImportingConcat.ts +36 -0
  70. package/src/extractor/errors.ts +1 -0
  71. package/src/extractor/esbuildAliasPlugin.ts +40 -0
  72. package/src/extractor/esbuildTsconfigPaths.ts +103 -0
  73. package/src/extractor/evaluateAstNode.ts +136 -0
  74. package/src/extractor/extractHelpers.ts +211 -0
  75. package/src/extractor/extractMediaStyle.ts +194 -0
  76. package/src/extractor/extractToClassNames.ts +631 -0
  77. package/src/extractor/extractToNative.ts +463 -0
  78. package/src/extractor/findTopmostFunction.ts +24 -0
  79. package/src/extractor/generatedUid.ts +41 -0
  80. package/src/extractor/getGuiConfigPathFromOptionsConfig.ts +24 -0
  81. package/src/extractor/getPrefixLogs.ts +9 -0
  82. package/src/extractor/getPropValueFromAttributes.ts +95 -0
  83. package/src/extractor/getSourceModule.ts +96 -0
  84. package/src/extractor/getStaticBindingsForScope.ts +237 -0
  85. package/src/extractor/hoistClassNames.ts +52 -0
  86. package/src/extractor/literalToAst.ts +85 -0
  87. package/src/extractor/loadFile.ts +17 -0
  88. package/src/extractor/loadGui.ts +487 -0
  89. package/src/extractor/logLines.ts +16 -0
  90. package/src/extractor/normalizeTernaries.ts +75 -0
  91. package/src/extractor/propsToFontFamilyCache.ts +18 -0
  92. package/src/extractor/regenerateConfig.ts +186 -0
  93. package/src/extractor/removeUnusedHooks.ts +83 -0
  94. package/src/extractor/timer.ts +25 -0
  95. package/src/extractor/validHTMLAttributes.ts +52 -0
  96. package/src/extractor/watchGuiConfig.ts +57 -0
  97. package/src/getPragmaOptions.ts +57 -0
  98. package/src/helpers/memoize.ts +24 -0
  99. package/src/helpers/requireGuiCore.ts +28 -0
  100. package/src/index.ts +4 -0
  101. package/src/registerRequire.ts +236 -0
  102. package/src/server.ts +43 -0
  103. package/src/setup.ts +0 -0
  104. package/src/types.ts +109 -0
  105. package/src/worker.ts +142 -0
  106. package/types/check-dep-versions.d.ts +37 -0
  107. package/types/check-dep-versions.d.ts.map +1 -0
  108. package/types/checkDeps.d.ts +19 -0
  109. package/types/checkDeps.d.ts.map +1 -0
  110. package/types/constants.d.ts +6 -0
  111. package/types/constants.d.ts.map +1 -0
  112. package/types/exports.d.ts +16 -0
  113. package/types/exports.d.ts.map +1 -0
  114. package/types/extractor/accessSafe.d.ts +3 -0
  115. package/types/extractor/accessSafe.d.ts.map +1 -0
  116. package/types/extractor/babelParse.d.ts +5 -0
  117. package/types/extractor/babelParse.d.ts.map +1 -0
  118. package/types/extractor/buildClassName.d.ts +7 -0
  119. package/types/extractor/buildClassName.d.ts.map +1 -0
  120. package/types/extractor/bundle.d.ts +121 -0
  121. package/types/extractor/bundle.d.ts.map +1 -0
  122. package/types/extractor/bundleConfig.d.ts +49 -0
  123. package/types/extractor/bundleConfig.d.ts.map +1 -0
  124. package/types/extractor/concatClassName.d.ts +8 -0
  125. package/types/extractor/concatClassName.d.ts.map +1 -0
  126. package/types/extractor/createEvaluator.d.ts +12 -0
  127. package/types/extractor/createEvaluator.d.ts.map +1 -0
  128. package/types/extractor/createExtractor.d.ts +32 -0
  129. package/types/extractor/createExtractor.d.ts.map +1 -0
  130. package/types/extractor/createLogger.d.ts +3 -0
  131. package/types/extractor/createLogger.d.ts.map +1 -0
  132. package/types/extractor/detectModuleFormat.d.ts +5 -0
  133. package/types/extractor/detectModuleFormat.d.ts.map +1 -0
  134. package/types/extractor/ensureImportingConcat.d.ts +4 -0
  135. package/types/extractor/ensureImportingConcat.d.ts.map +1 -0
  136. package/types/extractor/errors.d.ts +3 -0
  137. package/types/extractor/errors.d.ts.map +1 -0
  138. package/types/extractor/esbuildAliasPlugin.d.ts +18 -0
  139. package/types/extractor/esbuildAliasPlugin.d.ts.map +1 -0
  140. package/types/extractor/esbuildTsconfigPaths.d.ts +11 -0
  141. package/types/extractor/esbuildTsconfigPaths.d.ts.map +1 -0
  142. package/types/extractor/evaluateAstNode.d.ts +3 -0
  143. package/types/extractor/evaluateAstNode.d.ts.map +1 -0
  144. package/types/extractor/extractHelpers.d.ts +28 -0
  145. package/types/extractor/extractHelpers.d.ts.map +1 -0
  146. package/types/extractor/extractMediaStyle.d.ts +11 -0
  147. package/types/extractor/extractMediaStyle.d.ts.map +1 -0
  148. package/types/extractor/extractToClassNames.d.ts +25 -0
  149. package/types/extractor/extractToClassNames.d.ts.map +1 -0
  150. package/types/extractor/extractToNative.d.ts +13 -0
  151. package/types/extractor/extractToNative.d.ts.map +1 -0
  152. package/types/extractor/findTopmostFunction.d.ts +4 -0
  153. package/types/extractor/findTopmostFunction.d.ts.map +1 -0
  154. package/types/extractor/generatedUid.d.ts +5 -0
  155. package/types/extractor/generatedUid.d.ts.map +1 -0
  156. package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts +3 -0
  157. package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts.map +1 -0
  158. package/types/extractor/getPrefixLogs.d.ts +3 -0
  159. package/types/extractor/getPrefixLogs.d.ts.map +1 -0
  160. package/types/extractor/getPropValueFromAttributes.d.ts +19 -0
  161. package/types/extractor/getPropValueFromAttributes.d.ts.map +1 -0
  162. package/types/extractor/getSourceModule.d.ts +16 -0
  163. package/types/extractor/getSourceModule.d.ts.map +1 -0
  164. package/types/extractor/getStaticBindingsForScope.d.ts +5 -0
  165. package/types/extractor/getStaticBindingsForScope.d.ts.map +1 -0
  166. package/types/extractor/hoistClassNames.d.ts +6 -0
  167. package/types/extractor/hoistClassNames.d.ts.map +1 -0
  168. package/types/extractor/literalToAst.d.ts +4 -0
  169. package/types/extractor/literalToAst.d.ts.map +1 -0
  170. package/types/extractor/loadFile.d.ts +1 -0
  171. package/types/extractor/loadFile.d.ts.map +1 -0
  172. package/types/extractor/loadGui.d.ts +22 -0
  173. package/types/extractor/loadGui.d.ts.map +1 -0
  174. package/types/extractor/logLines.d.ts +2 -0
  175. package/types/extractor/logLines.d.ts.map +1 -0
  176. package/types/extractor/normalizeTernaries.d.ts +3 -0
  177. package/types/extractor/normalizeTernaries.d.ts.map +1 -0
  178. package/types/extractor/propsToFontFamilyCache.d.ts +4 -0
  179. package/types/extractor/propsToFontFamilyCache.d.ts.map +1 -0
  180. package/types/extractor/regenerateConfig.d.ts +9 -0
  181. package/types/extractor/regenerateConfig.d.ts.map +1 -0
  182. package/types/extractor/removeUnusedHooks.d.ts +3 -0
  183. package/types/extractor/removeUnusedHooks.d.ts.map +1 -0
  184. package/types/extractor/timer.d.ts +5 -0
  185. package/types/extractor/timer.d.ts.map +1 -0
  186. package/types/extractor/validHTMLAttributes.d.ts +52 -0
  187. package/types/extractor/validHTMLAttributes.d.ts.map +1 -0
  188. package/types/extractor/watchGuiConfig.d.ts +5 -0
  189. package/types/extractor/watchGuiConfig.d.ts.map +1 -0
  190. package/types/getPragmaOptions.d.ts +8 -0
  191. package/types/getPragmaOptions.d.ts.map +1 -0
  192. package/types/helpers/memoize.d.ts +8 -0
  193. package/types/helpers/memoize.d.ts.map +1 -0
  194. package/types/helpers/requireGuiCore.d.ts +3 -0
  195. package/types/helpers/requireGuiCore.d.ts.map +1 -0
  196. package/types/index.d.ts +4 -0
  197. package/types/index.d.ts.map +1 -0
  198. package/types/registerRequire.d.ts +10 -0
  199. package/types/registerRequire.d.ts.map +1 -0
  200. package/types/server.d.ts +3 -0
  201. package/types/server.d.ts.map +1 -0
  202. package/types/setup.d.ts +1 -0
  203. package/types/setup.d.ts.map +1 -0
  204. package/types/types.d.ts +92 -0
  205. package/types/types.d.ts.map +1 -0
  206. package/types/worker.d.ts +46 -0
  207. package/types/worker.d.ts.map +1 -0
@@ -0,0 +1,487 @@
1
+ import { basename, dirname, extname, join, relative, resolve } from 'node:path'
2
+ // @ts-ignore why
3
+ import { Color, colorLog } from '@hanzogui/cli-color'
4
+ import type { CLIResolvedOptions, CLIUserOptions, GuiOptions } from '@hanzogui/types'
5
+ import type { GuiInternalConfig } from '@hanzogui/web'
6
+ import esbuild from 'esbuild'
7
+ import * as esbuildWasm from 'esbuild-wasm'
8
+ import * as fsExtra from 'fs-extra'
9
+
10
+ import { SHOULD_DEBUG } from '../constants'
11
+ import { requireGuiCore } from '../helpers/requireGuiCore'
12
+ import { getNameToPaths, registerRequire } from '../registerRequire'
13
+ import {
14
+ type GuiProjectInfo,
15
+ getBundledConfig,
16
+ getLoadedConfig,
17
+ hasBundledConfigChanged,
18
+ loadComponentsSync,
19
+ writeGuiCSS,
20
+ } from './bundleConfig'
21
+ import { getGuiConfigPathFromOptionsConfig } from './getGuiConfigPathFromOptionsConfig'
22
+ import {
23
+ generateGuiThemes,
24
+ regenerateConfig,
25
+ regenerateConfigSync,
26
+ } from './regenerateConfig'
27
+
28
+ const getFilledOptions = (propsIn: Partial<GuiOptions>): GuiOptions => ({
29
+ // defaults
30
+ platform: (process.env.HANZO_GUI_TARGET as any) || 'web',
31
+ config: 'gui.config.ts',
32
+ components: ['@hanzo/gui'],
33
+ ...(propsIn as Partial<GuiOptions>),
34
+ })
35
+
36
+ let isLoadingPromise: null | Promise<any>
37
+
38
+ export async function loadGui(
39
+ propsIn: Partial<GuiOptions>
40
+ ): Promise<GuiProjectInfo | null> {
41
+ if (isLoadingPromise) return await isLoadingPromise
42
+
43
+ let resolvePromise
44
+ let rejectPromise
45
+ isLoadingPromise = new Promise((res, rej) => {
46
+ resolvePromise = res
47
+ rejectPromise = rej
48
+ })
49
+
50
+ try {
51
+ const props = getFilledOptions(propsIn)
52
+
53
+ const bundleInfo = await getBundledConfig(props)
54
+ if (!bundleInfo) {
55
+ console.warn(
56
+ `No bundled config generated, maybe an error in bundling. Set DEBUG=hanzo-gui and re-run to get logs.`
57
+ )
58
+ resolvePromise(null)
59
+ return null
60
+ }
61
+
62
+ // this affects the bundled config so run it first
63
+ await generateThemesAndLog(props)
64
+
65
+ // if they accidently pass in a config without createGui called,call it
66
+ const maybeGuiConfig = bundleInfo.guiConfig as GuiInternalConfig
67
+ if (maybeGuiConfig && !maybeGuiConfig.parsed) {
68
+ const { createGui } = requireGuiCore(props.platform || 'web')
69
+ bundleInfo.guiConfig = createGui(bundleInfo.guiConfig as any)
70
+ }
71
+
72
+ if (!hasBundledConfigChanged()) {
73
+ resolvePromise(bundleInfo)
74
+ return bundleInfo
75
+ }
76
+
77
+ await regenerateConfig(props, bundleInfo)
78
+
79
+ resolvePromise(bundleInfo)
80
+ return bundleInfo
81
+ } catch (err) {
82
+ rejectPromise()
83
+ throw err
84
+ } finally {
85
+ isLoadingPromise = null
86
+ }
87
+ }
88
+
89
+ // debounce a bit
90
+ let waiting = false
91
+
92
+ export const generateThemesAndLog = async (options: GuiOptions, force = false) => {
93
+ if (waiting) return
94
+ if (!options.themeBuilder) return
95
+ try {
96
+ waiting = true
97
+ await new Promise((res) => setTimeout(res, 30))
98
+ const didGenerate = await generateGuiThemes(options, force)
99
+
100
+ // only logs when changed
101
+ if (didGenerate) {
102
+ const whitespaceBefore = ` `
103
+ colorLog(
104
+ Color.FgYellow,
105
+ `${whitespaceBefore}➡ [hanzo-gui] generated themes: ${relative(
106
+ process.cwd(),
107
+ options.themeBuilder.output
108
+ )}`
109
+ )
110
+
111
+ if (options.outputCSS) {
112
+ const loadedConfig = getLoadedConfig()
113
+ if (loadedConfig) {
114
+ await writeGuiCSS(options.outputCSS, loadedConfig)
115
+ }
116
+ }
117
+ }
118
+ } finally {
119
+ waiting = false
120
+ }
121
+ }
122
+
123
+ const last: Record<string, GuiProjectInfo | null> = {}
124
+ const lastVersion: Record<string, string> = {}
125
+
126
+ // esbuild-wasm state - initialized once per process
127
+ let esbuildWasmInitialized = false
128
+
129
+ /**
130
+ * Load gui.build.ts config using esbuild-wasm transform
131
+ * Uses WASM to avoid native esbuild service lifecycle issues (EPIPE errors)
132
+ */
133
+ export async function loadGuiBuildConfigAsync(
134
+ guiOptions: Partial<GuiOptions> | undefined
135
+ ): Promise<GuiOptions> {
136
+ const buildFilePath = guiOptions?.buildFile ?? './gui.build.ts'
137
+ const absolutePath =
138
+ buildFilePath[0] === '.' ? join(process.cwd(), buildFilePath) : buildFilePath
139
+
140
+ if (fsExtra.existsSync(absolutePath)) {
141
+ try {
142
+ const source = await fsExtra.readFile(absolutePath, 'utf-8')
143
+
144
+ // initialize esbuild-wasm once
145
+ if (!esbuildWasmInitialized) {
146
+ await esbuildWasm.initialize({})
147
+ esbuildWasmInitialized = true
148
+ }
149
+
150
+ // use esbuild-wasm.transform to compile - no native service needed
151
+ const result = await esbuildWasm.transform(source, {
152
+ loader: 'ts',
153
+ format: 'cjs',
154
+ target: 'node18',
155
+ sourcefile: absolutePath,
156
+ })
157
+
158
+ // evaluate the compiled code to get the exports
159
+ // pass process so process.env works in the config
160
+ const module = { exports: {} as any }
161
+ const fn = new Function('module', 'exports', 'require', 'process', result.code)
162
+ fn(module, module.exports, require, process)
163
+
164
+ const out = module.exports.default || module.exports
165
+ if (!out || typeof out !== 'object') {
166
+ throw new Error(`No default export found in ${buildFilePath}: ${out}`)
167
+ }
168
+
169
+ guiOptions = {
170
+ ...guiOptions,
171
+ ...out,
172
+ }
173
+ } catch (err) {
174
+ console.error(`[hanzo-gui] Error loading ${buildFilePath}:`, err)
175
+ throw err
176
+ }
177
+ }
178
+
179
+ if (!guiOptions) {
180
+ throw new Error(
181
+ `No hanzo-gui build options found either via input props or at gui.build.ts`
182
+ )
183
+ }
184
+
185
+ return {
186
+ config: 'gui.config.ts',
187
+ components: ['@hanzo/gui', '@hanzogui/core'],
188
+ ...guiOptions,
189
+ } as GuiOptions
190
+ }
191
+
192
+ /**
193
+ * @deprecated Use loadGuiBuildConfigAsync instead to avoid EPIPE errors
194
+ */
195
+ export function loadGuiBuildConfigSync(
196
+ guiOptions: Partial<GuiOptions> | undefined
197
+ ) {
198
+ const buildFilePath = guiOptions?.buildFile ?? './gui.build.ts'
199
+ if (fsExtra.existsSync(buildFilePath)) {
200
+ const registered = registerRequire('web')
201
+ try {
202
+ const out = require(
203
+ buildFilePath[0] === '.' ? join(process.cwd(), buildFilePath) : buildFilePath
204
+ ).default
205
+ if (!out) {
206
+ throw new Error(`No default export found in ${buildFilePath}: ${out}`)
207
+ }
208
+
209
+ guiOptions = {
210
+ ...guiOptions,
211
+ ...out,
212
+ }
213
+ } finally {
214
+ registered.unregister()
215
+ }
216
+ }
217
+ if (!guiOptions) {
218
+ throw new Error(
219
+ `No hanzo-gui build options found either via input props or at gui.build.ts`
220
+ )
221
+ }
222
+ return {
223
+ config: 'gui.config.ts',
224
+ components: ['@hanzo/gui', '@hanzogui/core'],
225
+ ...guiOptions,
226
+ } as GuiOptions
227
+ }
228
+
229
+ // loads in-process using esbuild-register
230
+ export function loadGuiSync({
231
+ forceExports,
232
+ cacheKey,
233
+ ...propsIn
234
+ }: Partial<GuiOptions> & {
235
+ forceExports?: boolean
236
+ cacheKey?: string
237
+ }): GuiProjectInfo {
238
+ const key = JSON.stringify(propsIn)
239
+
240
+ if (last[key] && !hasBundledConfigChanged()) {
241
+ if (!lastVersion[key] || lastVersion[key] === cacheKey) {
242
+ return last[key]!
243
+ }
244
+ }
245
+
246
+ lastVersion[key] = cacheKey || ''
247
+
248
+ const props = getFilledOptions(propsIn)
249
+
250
+ // lets shim require and avoid importing react-native + react-native-web
251
+ // we just need to read the config around them
252
+ process.env.IS_STATIC = 'is_static'
253
+ process.env.HANZO_GUI_IS_SERVER = 'true'
254
+
255
+ const { unregister } = registerRequire(props.platform || 'web', {
256
+ proxyWormImports: !!forceExports,
257
+ })
258
+
259
+ try {
260
+ const devValueOG = globalThis['__DEV__' as any]
261
+ globalThis['__DEV__' as any] = process.env.NODE_ENV === 'development'
262
+
263
+ try {
264
+ // config
265
+ let guiConfig: GuiInternalConfig | null = null
266
+ if (propsIn.config) {
267
+ const configPath = getGuiConfigPathFromOptionsConfig(propsIn.config)
268
+ const exp = require(configPath)
269
+
270
+ if (!exp || exp._isProxyWorm) {
271
+ throw new Error(`Got a empty / proxied config!`)
272
+ }
273
+
274
+ guiConfig = (exp['default'] || exp['config'] || exp) as GuiInternalConfig
275
+
276
+ if (!guiConfig || !guiConfig.parsed) {
277
+ const confPath = require.resolve(configPath)
278
+ throw new Error(`Can't find valid config in ${confPath}:
279
+
280
+ Be sure you "export default" or "export const config" the config.`)
281
+ }
282
+
283
+ // set up core
284
+ if (guiConfig) {
285
+ const { createGui } = requireGuiCore(props.platform || 'web')
286
+ createGui(guiConfig as any)
287
+ }
288
+ }
289
+
290
+ // components
291
+ const components = loadComponentsSync(props, forceExports)
292
+ if (!components) {
293
+ throw new Error(`No components loaded`)
294
+ }
295
+ if (process.env.DEBUG === '@hanzo/gui') {
296
+ console.info(`components`, components)
297
+ }
298
+
299
+ // undo shims
300
+ process.env.IS_STATIC = undefined
301
+ globalThis['__DEV__' as any] = devValueOG
302
+
303
+ const info = {
304
+ components,
305
+ guiConfig,
306
+ nameToPaths: getNameToPaths(),
307
+ } satisfies GuiProjectInfo
308
+
309
+ if (guiConfig) {
310
+ const { outputCSS } = props
311
+ if (outputCSS) {
312
+ writeGuiCSS(outputCSS, guiConfig)
313
+ }
314
+
315
+ regenerateConfigSync(props, info)
316
+ }
317
+
318
+ last[key] = {
319
+ ...info,
320
+ cached: true,
321
+ }
322
+
323
+ return info as any
324
+ } catch (err) {
325
+ if (err instanceof Error) {
326
+ if (!SHOULD_DEBUG && !forceExports) {
327
+ console.warn(
328
+ `Error loading gui.config.ts (set DEBUG=hanzo-gui to see full stack), running hanzo-gui without custom config`
329
+ )
330
+ console.info(`\n\n ${err.message}\n\n`)
331
+ } else {
332
+ if (SHOULD_DEBUG) {
333
+ console.error(err)
334
+ }
335
+ }
336
+ } else {
337
+ console.error(`Error loading gui.config.ts`, err)
338
+ }
339
+
340
+ return {
341
+ components: [],
342
+ guiConfig: null,
343
+ nameToPaths: {},
344
+ }
345
+ }
346
+ } finally {
347
+ unregister()
348
+ }
349
+ }
350
+
351
+ export async function getOptions({
352
+ root = process.cwd(),
353
+ tsconfigPath = 'tsconfig.json',
354
+ guiOptions,
355
+ host,
356
+ debug,
357
+ }: Partial<CLIUserOptions> = {}): Promise<CLIResolvedOptions> {
358
+ const dotDir = join(root, '.gui')
359
+ let pkgJson = {}
360
+
361
+ try {
362
+ pkgJson = await fsExtra.readJSON(join(root, 'package.json'))
363
+ } catch (err) {
364
+ // ok
365
+ }
366
+
367
+ return {
368
+ mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
369
+ root,
370
+ host: host || '127.0.0.1',
371
+ pkgJson,
372
+ debug,
373
+ tsconfigPath,
374
+ guiOptions: {
375
+ platform: (process.env.HANZO_GUI_TARGET as any) || 'web',
376
+ components: ['@hanzo/gui'],
377
+ ...guiOptions,
378
+ config:
379
+ guiOptions?.config ??
380
+ (await getDefaultGuiConfigPath(root, guiOptions?.config)),
381
+ },
382
+ paths: {
383
+ root,
384
+ dotDir,
385
+ conf: join(dotDir, 'gui.config.json'),
386
+ types: join(dotDir, 'types.json'),
387
+ },
388
+ }
389
+ }
390
+
391
+ export function resolveWebOrNativeSpecificEntry(entry: string) {
392
+ const workspaceRoot = resolve()
393
+ const resolved = require.resolve(entry, { paths: [workspaceRoot] })
394
+ const ext = extname(resolved)
395
+ const fileName = basename(resolved).replace(ext, '')
396
+ const specificExt = process.env.HANZO_GUI_TARGET === 'web' ? 'web' : 'native'
397
+ const specificFile = join(dirname(resolved), fileName + '.' + specificExt + ext)
398
+ if (fsExtra.existsSync(specificFile)) {
399
+ return specificFile
400
+ }
401
+ return entry
402
+ }
403
+
404
+ const defaultPaths = ['gui.config.ts', join('src', 'gui.config.ts')]
405
+ let hasWarnedOnce = false
406
+
407
+ async function getDefaultGuiConfigPath(root: string, configPath?: string) {
408
+ const searchPaths = [
409
+ ...new Set(
410
+ [configPath, ...defaultPaths].filter(Boolean).map((p) => join(root, p as string))
411
+ ),
412
+ ]
413
+
414
+ for (const path of searchPaths) {
415
+ if (await fsExtra.pathExists(path)) {
416
+ return path
417
+ }
418
+ }
419
+
420
+ if (!hasWarnedOnce) {
421
+ hasWarnedOnce = true
422
+ console.warn(`Warning: couldn't find gui.config.ts in the following paths given configuration "${configPath}":
423
+ ${searchPaths.join(`\n `)}
424
+ `)
425
+ }
426
+ }
427
+
428
+ export type { GuiProjectInfo }
429
+
430
+ export async function esbuildWatchFiles(entry: string, onChanged: () => void) {
431
+ let hasRunOnce = false
432
+
433
+ /**
434
+ * We're just (ab)using this as a file watcher, so bundle = true to follow paths
435
+ * and then write: false and logLevel silent to avoid all errors
436
+ */
437
+
438
+ const context = await esbuild.context({
439
+ bundle: true,
440
+ entryPoints: [entry],
441
+ resolveExtensions: ['.ts', '.tsx', '.js', '.mjs'],
442
+ logLevel: 'silent',
443
+ write: false,
444
+
445
+ alias: {
446
+ '@react-native/normalize-color': '@hanzogui/proxy-worm',
447
+ 'react-native-web': '@hanzogui/react-native-web-lite',
448
+ 'react-native': '@hanzogui/proxy-worm',
449
+ },
450
+
451
+ plugins: [
452
+ // to log what its watching:
453
+ // {
454
+ // name: 'test',
455
+ // setup({ onResolve }) {
456
+ // onResolve({ filter: /.*/ }, (args) => {
457
+ // console.log('wtf', args.path)
458
+ // })
459
+ // },
460
+ // },
461
+
462
+ {
463
+ name: `on-rebuild`,
464
+ setup({ onEnd, onResolve }) {
465
+ // external node modules
466
+ let filter = /^[^./]|^\.[^./]|^\.\.[^/]/ // Must not start with "/" or "./" or "../"
467
+ onResolve({ filter }, (args) => ({ path: args.path, external: true }))
468
+
469
+ onEnd(() => {
470
+ if (!hasRunOnce) {
471
+ hasRunOnce = true
472
+ } else {
473
+ onChanged()
474
+ }
475
+ })
476
+ },
477
+ },
478
+ ],
479
+ })
480
+
481
+ // just returns after dispose is called i think
482
+ void context.watch()
483
+
484
+ return () => {
485
+ context.dispose()
486
+ }
487
+ }
@@ -0,0 +1,16 @@
1
+ const prefix = ' '
2
+
3
+ export const logLines = (str: string, singleLine = false) => {
4
+ if (singleLine) {
5
+ return prefix + str.split(' ').join(`\n${prefix}`)
6
+ }
7
+ const lines: string[] = ['']
8
+ const items = str.split(' ')
9
+ for (const item of items) {
10
+ if (item.length + lines[lines.length - 1].length > 85) {
11
+ lines.push('')
12
+ }
13
+ lines[lines.length - 1] += item + ' '
14
+ }
15
+ return lines.map((line, i) => prefix + (i == 0 ? '' : ' ') + line.trim()).join('\n')
16
+ }
@@ -0,0 +1,75 @@
1
+ import generate from '@babel/generator'
2
+ import * as t from '@babel/types'
3
+ import { mergeProps } from '@hanzogui/web'
4
+ import invariant from 'invariant'
5
+ import type { Ternary } from '../types'
6
+ import { forwardFontFamilyName } from './propsToFontFamilyCache'
7
+
8
+ export function normalizeTernaries(ternaries: Ternary[]) {
9
+ invariant(
10
+ Array.isArray(ternaries),
11
+ 'extractStaticTernaries expects param 1 to be an array of ternaries'
12
+ )
13
+
14
+ if (ternaries.length === 0) {
15
+ return []
16
+ }
17
+
18
+ const ternariesByKey: { [key: string]: Ternary } = {}
19
+
20
+ for (let idx = -1, len = ternaries.length; ++idx < len; ) {
21
+ const { test, consequent, alternate, remove, ...rest } = ternaries[idx]
22
+
23
+ let ternaryTest = test
24
+
25
+ // strip parens
26
+ if (t.isExpressionStatement(test)) {
27
+ ternaryTest = (test as any).expression
28
+ }
29
+
30
+ // convert `!thing` to `thing` with swapped consequent and alternate
31
+ let shouldSwap = false
32
+ if (t.isUnaryExpression(test) && test.operator === '!') {
33
+ ternaryTest = test.argument
34
+ shouldSwap = true
35
+ } else if (t.isBinaryExpression(test)) {
36
+ if (test.operator === '!==' || test.operator === '!=') {
37
+ ternaryTest = t.binaryExpression(
38
+ test.operator.replace('!', '=') as any,
39
+ test.left,
40
+ test.right
41
+ )
42
+ shouldSwap = true
43
+ }
44
+ }
45
+
46
+ // @ts-ignore
47
+ const key = generate(ternaryTest as any).code
48
+
49
+ if (!ternariesByKey[key]) {
50
+ ternariesByKey[key] = {
51
+ ...rest,
52
+ alternate: {},
53
+ consequent: {},
54
+ test: ternaryTest,
55
+ remove,
56
+ }
57
+ }
58
+ const altStyle = (shouldSwap ? consequent : alternate) ?? {}
59
+ const consStyle = (shouldSwap ? alternate : consequent) ?? {}
60
+
61
+ const nextAlt = ternariesByKey[key].alternate!
62
+ ternariesByKey[key].alternate = mergeProps(altStyle, nextAlt)
63
+ forwardFontFamilyName(altStyle, ternariesByKey[key].alternate)
64
+
65
+ const nextCons = ternariesByKey[key].consequent!
66
+ ternariesByKey[key].consequent = mergeProps(consStyle, nextCons)
67
+ forwardFontFamilyName(consStyle, ternariesByKey[key].consequent)
68
+ }
69
+
70
+ const ternaryExpression = Object.keys(ternariesByKey).map((key) => {
71
+ return ternariesByKey[key]
72
+ })
73
+
74
+ return ternaryExpression
75
+ }
@@ -0,0 +1,18 @@
1
+ // weird stuff
2
+
3
+ const cache = new WeakMap<any, string>()
4
+
5
+ export function setPropsToFontFamily(props: any, ff: string) {
6
+ cache.set(props, ff.replace('$', '').trim())
7
+ }
8
+
9
+ export function getFontFamilyNameFromProps(props: any) {
10
+ return cache.get(props)
11
+ }
12
+
13
+ export function forwardFontFamilyName(prev: any, next: any, fallback?: string) {
14
+ const ff = getFontFamilyNameFromProps(prev) || fallback
15
+ if (ff) {
16
+ setPropsToFontFamily(next, ff)
17
+ }
18
+ }