zyzz 0.0.0 → 0.0.2

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 (678) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +380 -0
  3. package/dist/Config.d.ts +170 -0
  4. package/dist/Config.d.ts.map +1 -0
  5. package/dist/Config.js +249 -0
  6. package/dist/Config.js.map +1 -0
  7. package/dist/Props.d.ts +7 -0
  8. package/dist/Props.d.ts.map +1 -0
  9. package/dist/Props.js +3 -0
  10. package/dist/Props.js.map +1 -0
  11. package/dist/Style.d.ts +167 -0
  12. package/dist/Style.d.ts.map +1 -0
  13. package/dist/Style.js +284 -0
  14. package/dist/Style.js.map +1 -0
  15. package/dist/Theme.d.ts +154 -0
  16. package/dist/Theme.d.ts.map +1 -0
  17. package/dist/Theme.js +257 -0
  18. package/dist/Theme.js.map +1 -0
  19. package/dist/babel/NativeEdits.d.ts +8 -0
  20. package/dist/babel/NativeEdits.d.ts.map +1 -0
  21. package/dist/babel/NativeEdits.js +233 -0
  22. package/dist/babel/NativeEdits.js.map +1 -0
  23. package/dist/babel/NativeJsx.d.ts +10 -0
  24. package/dist/babel/NativeJsx.d.ts.map +1 -0
  25. package/dist/babel/NativeJsx.js +204 -0
  26. package/dist/babel/NativeJsx.js.map +1 -0
  27. package/dist/babel/index.d.ts +51 -0
  28. package/dist/babel/index.d.ts.map +1 -0
  29. package/dist/babel/index.js +220 -0
  30. package/dist/babel/index.js.map +1 -0
  31. package/dist/cli/index.d.ts +3 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/index.js +178 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/compiler/Graph.d.ts +64 -0
  36. package/dist/compiler/Graph.d.ts.map +1 -0
  37. package/dist/compiler/Graph.js +1111 -0
  38. package/dist/compiler/Graph.js.map +1 -0
  39. package/dist/compiler/Native.d.ts +53 -0
  40. package/dist/compiler/Native.d.ts.map +1 -0
  41. package/dist/compiler/Native.js +617 -0
  42. package/dist/compiler/Native.js.map +1 -0
  43. package/dist/compiler/Source.d.ts +165 -0
  44. package/dist/compiler/Source.d.ts.map +1 -0
  45. package/dist/compiler/Source.js +990 -0
  46. package/dist/compiler/Source.js.map +1 -0
  47. package/dist/compiler/Transform.d.ts +57 -0
  48. package/dist/compiler/Transform.d.ts.map +1 -0
  49. package/dist/compiler/Transform.js +884 -0
  50. package/dist/compiler/Transform.js.map +1 -0
  51. package/dist/compiler/index.d.ts +13 -0
  52. package/dist/compiler/index.d.ts.map +1 -0
  53. package/dist/compiler/index.js +13 -0
  54. package/dist/compiler/index.js.map +1 -0
  55. package/dist/compiler/internal/Applications.d.ts +35 -0
  56. package/dist/compiler/internal/Applications.d.ts.map +1 -0
  57. package/dist/compiler/internal/Applications.js +248 -0
  58. package/dist/compiler/internal/Applications.js.map +1 -0
  59. package/dist/compiler/internal/AtRules.d.ts +8 -0
  60. package/dist/compiler/internal/AtRules.d.ts.map +1 -0
  61. package/dist/compiler/internal/AtRules.js +180 -0
  62. package/dist/compiler/internal/AtRules.js.map +1 -0
  63. package/dist/compiler/internal/Catalogs.d.ts +19 -0
  64. package/dist/compiler/internal/Catalogs.d.ts.map +1 -0
  65. package/dist/compiler/internal/Catalogs.js +68 -0
  66. package/dist/compiler/internal/Catalogs.js.map +1 -0
  67. package/dist/compiler/internal/ColorProfiles.d.ts +3 -0
  68. package/dist/compiler/internal/ColorProfiles.d.ts.map +1 -0
  69. package/dist/compiler/internal/ColorProfiles.js +84 -0
  70. package/dist/compiler/internal/ColorProfiles.js.map +1 -0
  71. package/dist/compiler/internal/CompositionBindings.d.ts +16 -0
  72. package/dist/compiler/internal/CompositionBindings.d.ts.map +1 -0
  73. package/dist/compiler/internal/CompositionBindings.js +89 -0
  74. package/dist/compiler/internal/CompositionBindings.js.map +1 -0
  75. package/dist/compiler/internal/Compositions.d.ts +32 -0
  76. package/dist/compiler/internal/Compositions.d.ts.map +1 -0
  77. package/dist/compiler/internal/Compositions.js +464 -0
  78. package/dist/compiler/internal/Compositions.js.map +1 -0
  79. package/dist/compiler/internal/Configurations.d.ts +21 -0
  80. package/dist/compiler/internal/Configurations.d.ts.map +1 -0
  81. package/dist/compiler/internal/Configurations.js +171 -0
  82. package/dist/compiler/internal/Configurations.js.map +1 -0
  83. package/dist/compiler/internal/Contract.d.ts +27 -0
  84. package/dist/compiler/internal/Contract.d.ts.map +1 -0
  85. package/dist/compiler/internal/Contract.js +600 -0
  86. package/dist/compiler/internal/Contract.js.map +1 -0
  87. package/dist/compiler/internal/Contributions.d.ts +54 -0
  88. package/dist/compiler/internal/Contributions.d.ts.map +1 -0
  89. package/dist/compiler/internal/Contributions.js +1109 -0
  90. package/dist/compiler/internal/Contributions.js.map +1 -0
  91. package/dist/compiler/internal/Descriptors.d.ts +15 -0
  92. package/dist/compiler/internal/Descriptors.d.ts.map +1 -0
  93. package/dist/compiler/internal/Descriptors.js +183 -0
  94. package/dist/compiler/internal/Descriptors.js.map +1 -0
  95. package/dist/compiler/internal/Dynamic.d.ts +14 -0
  96. package/dist/compiler/internal/Dynamic.d.ts.map +1 -0
  97. package/dist/compiler/internal/Dynamic.js +172 -0
  98. package/dist/compiler/internal/Dynamic.js.map +1 -0
  99. package/dist/compiler/internal/Edits.d.ts +12 -0
  100. package/dist/compiler/internal/Edits.d.ts.map +1 -0
  101. package/dist/compiler/internal/Edits.js +5 -0
  102. package/dist/compiler/internal/Edits.js.map +1 -0
  103. package/dist/compiler/internal/Expression.d.ts +12 -0
  104. package/dist/compiler/internal/Expression.d.ts.map +1 -0
  105. package/dist/compiler/internal/Expression.js +98 -0
  106. package/dist/compiler/internal/Expression.js.map +1 -0
  107. package/dist/compiler/internal/Functions.d.ts +5 -0
  108. package/dist/compiler/internal/Functions.d.ts.map +1 -0
  109. package/dist/compiler/internal/Functions.js +191 -0
  110. package/dist/compiler/internal/Functions.js.map +1 -0
  111. package/dist/compiler/internal/Identifiers.d.ts +9 -0
  112. package/dist/compiler/internal/Identifiers.d.ts.map +1 -0
  113. package/dist/compiler/internal/Identifiers.js +106 -0
  114. package/dist/compiler/internal/Identifiers.js.map +1 -0
  115. package/dist/compiler/internal/Keyframes.d.ts +5 -0
  116. package/dist/compiler/internal/Keyframes.d.ts.map +1 -0
  117. package/dist/compiler/internal/Keyframes.js +51 -0
  118. package/dist/compiler/internal/Keyframes.js.map +1 -0
  119. package/dist/compiler/internal/Namespaces.d.ts +17 -0
  120. package/dist/compiler/internal/Namespaces.d.ts.map +1 -0
  121. package/dist/compiler/internal/Namespaces.js +265 -0
  122. package/dist/compiler/internal/Namespaces.js.map +1 -0
  123. package/dist/compiler/internal/NativeBindings.d.ts +74 -0
  124. package/dist/compiler/internal/NativeBindings.d.ts.map +1 -0
  125. package/dist/compiler/internal/NativeBindings.js +117 -0
  126. package/dist/compiler/internal/NativeBindings.js.map +1 -0
  127. package/dist/compiler/internal/PackedStyles.d.ts +35 -0
  128. package/dist/compiler/internal/PackedStyles.d.ts.map +1 -0
  129. package/dist/compiler/internal/PackedStyles.js +345 -0
  130. package/dist/compiler/internal/PackedStyles.js.map +1 -0
  131. package/dist/compiler/internal/Properties.d.ts +5 -0
  132. package/dist/compiler/internal/Properties.d.ts.map +1 -0
  133. package/dist/compiler/internal/Properties.js +82 -0
  134. package/dist/compiler/internal/Properties.js.map +1 -0
  135. package/dist/compiler/internal/RecipeConditions.d.ts +41 -0
  136. package/dist/compiler/internal/RecipeConditions.d.ts.map +1 -0
  137. package/dist/compiler/internal/RecipeConditions.js +82 -0
  138. package/dist/compiler/internal/RecipeConditions.js.map +1 -0
  139. package/dist/compiler/internal/RecipePayloads.d.ts +31 -0
  140. package/dist/compiler/internal/RecipePayloads.d.ts.map +1 -0
  141. package/dist/compiler/internal/RecipePayloads.js +99 -0
  142. package/dist/compiler/internal/RecipePayloads.js.map +1 -0
  143. package/dist/compiler/internal/Recipes.d.ts +32 -0
  144. package/dist/compiler/internal/Recipes.d.ts.map +1 -0
  145. package/dist/compiler/internal/Recipes.js +339 -0
  146. package/dist/compiler/internal/Recipes.js.map +1 -0
  147. package/dist/compiler/internal/Relative.d.ts +19 -0
  148. package/dist/compiler/internal/Relative.d.ts.map +1 -0
  149. package/dist/compiler/internal/Relative.js +62 -0
  150. package/dist/compiler/internal/Relative.js.map +1 -0
  151. package/dist/compiler/internal/Scope.d.ts +10 -0
  152. package/dist/compiler/internal/Scope.d.ts.map +1 -0
  153. package/dist/compiler/internal/Scope.js +28 -0
  154. package/dist/compiler/internal/Scope.js.map +1 -0
  155. package/dist/compiler/internal/Selectors.d.ts +12 -0
  156. package/dist/compiler/internal/Selectors.d.ts.map +1 -0
  157. package/dist/compiler/internal/Selectors.js +265 -0
  158. package/dist/compiler/internal/Selectors.js.map +1 -0
  159. package/dist/compiler/internal/Static.d.ts +39 -0
  160. package/dist/compiler/internal/Static.d.ts.map +1 -0
  161. package/dist/compiler/internal/Static.js +532 -0
  162. package/dist/compiler/internal/Static.js.map +1 -0
  163. package/dist/compiler/internal/Stylesheets.d.ts +47 -0
  164. package/dist/compiler/internal/Stylesheets.d.ts.map +1 -0
  165. package/dist/compiler/internal/Stylesheets.js +272 -0
  166. package/dist/compiler/internal/Stylesheets.js.map +1 -0
  167. package/dist/compiler/internal/Syntax.d.ts +17 -0
  168. package/dist/compiler/internal/Syntax.d.ts.map +1 -0
  169. package/dist/compiler/internal/Syntax.js +19 -0
  170. package/dist/compiler/internal/Syntax.js.map +1 -0
  171. package/dist/compiler/internal/Themes.d.ts +158 -0
  172. package/dist/compiler/internal/Themes.d.ts.map +1 -0
  173. package/dist/compiler/internal/Themes.js +1169 -0
  174. package/dist/compiler/internal/Themes.js.map +1 -0
  175. package/dist/compiler/internal/Variables.d.ts +31 -0
  176. package/dist/compiler/internal/Variables.d.ts.map +1 -0
  177. package/dist/compiler/internal/Variables.js +376 -0
  178. package/dist/compiler/internal/Variables.js.map +1 -0
  179. package/dist/compiler/internal/ViewTransitions.d.ts +3 -0
  180. package/dist/compiler/internal/ViewTransitions.d.ts.map +1 -0
  181. package/dist/compiler/internal/ViewTransitions.js +68 -0
  182. package/dist/compiler/internal/ViewTransitions.js.map +1 -0
  183. package/dist/cx.d.ts +18 -0
  184. package/dist/cx.d.ts.map +1 -0
  185. package/dist/cx.js +60 -0
  186. package/dist/cx.js.map +1 -0
  187. package/dist/default.d.ts +2008 -0
  188. package/dist/default.d.ts.map +1 -0
  189. package/dist/default.js +243 -0
  190. package/dist/default.js.map +7 -0
  191. package/dist/default.js.zyzz.json +1 -0
  192. package/dist/index.d.ts +21 -0
  193. package/dist/index.d.ts.map +1 -0
  194. package/dist/index.js +19 -0
  195. package/dist/index.js.map +1 -0
  196. package/dist/internal/Authoring.d.ts +26 -0
  197. package/dist/internal/Authoring.d.ts.map +1 -0
  198. package/dist/internal/Authoring.js +134 -0
  199. package/dist/internal/Authoring.js.map +1 -0
  200. package/dist/internal/Binding.d.ts +64 -0
  201. package/dist/internal/Binding.d.ts.map +1 -0
  202. package/dist/internal/Binding.js +27 -0
  203. package/dist/internal/Binding.js.map +1 -0
  204. package/dist/internal/BindingDomains.d.ts +11 -0
  205. package/dist/internal/BindingDomains.d.ts.map +1 -0
  206. package/dist/internal/BindingDomains.js +459 -0
  207. package/dist/internal/BindingDomains.js.map +1 -0
  208. package/dist/internal/Cascade.d.ts +45 -0
  209. package/dist/internal/Cascade.d.ts.map +1 -0
  210. package/dist/internal/Cascade.js +165 -0
  211. package/dist/internal/Cascade.js.map +1 -0
  212. package/dist/internal/Compound.d.ts +132 -0
  213. package/dist/internal/Compound.d.ts.map +1 -0
  214. package/dist/internal/Compound.js +2 -0
  215. package/dist/internal/Compound.js.map +1 -0
  216. package/dist/internal/Condition.d.ts +33 -0
  217. package/dist/internal/Condition.d.ts.map +1 -0
  218. package/dist/internal/Condition.js +180 -0
  219. package/dist/internal/Condition.js.map +1 -0
  220. package/dist/internal/Corner.d.ts +9 -0
  221. package/dist/internal/Corner.d.ts.map +1 -0
  222. package/dist/internal/Corner.js +14 -0
  223. package/dist/internal/Corner.js.map +1 -0
  224. package/dist/internal/FunctionSyntax.d.ts +27 -0
  225. package/dist/internal/FunctionSyntax.d.ts.map +1 -0
  226. package/dist/internal/FunctionSyntax.js +91 -0
  227. package/dist/internal/FunctionSyntax.js.map +1 -0
  228. package/dist/internal/FunctionValue.d.ts +19 -0
  229. package/dist/internal/FunctionValue.d.ts.map +1 -0
  230. package/dist/internal/FunctionValue.js +2 -0
  231. package/dist/internal/FunctionValue.js.map +1 -0
  232. package/dist/internal/Geometry.d.ts +8 -0
  233. package/dist/internal/Geometry.d.ts.map +1 -0
  234. package/dist/internal/Geometry.js +2 -0
  235. package/dist/internal/Geometry.js.map +1 -0
  236. package/dist/internal/Grid.d.ts +15 -0
  237. package/dist/internal/Grid.d.ts.map +1 -0
  238. package/dist/internal/Grid.js +2 -0
  239. package/dist/internal/Grid.js.map +1 -0
  240. package/dist/internal/Identifier.d.ts +15 -0
  241. package/dist/internal/Identifier.d.ts.map +1 -0
  242. package/dist/internal/Identifier.js +2 -0
  243. package/dist/internal/Identifier.js.map +1 -0
  244. package/dist/internal/Identity.d.ts +16 -0
  245. package/dist/internal/Identity.d.ts.map +1 -0
  246. package/dist/internal/Identity.js +78 -0
  247. package/dist/internal/Identity.js.map +1 -0
  248. package/dist/internal/Lexical.d.ts +89 -0
  249. package/dist/internal/Lexical.d.ts.map +1 -0
  250. package/dist/internal/Lexical.js +15 -0
  251. package/dist/internal/Lexical.js.map +1 -0
  252. package/dist/internal/Literal.d.ts +3459 -0
  253. package/dist/internal/Literal.d.ts.map +1 -0
  254. package/dist/internal/Literal.js +3371 -0
  255. package/dist/internal/Literal.js.map +1 -0
  256. package/dist/internal/NativeProperties.d.ts +596 -0
  257. package/dist/internal/NativeProperties.d.ts.map +1 -0
  258. package/dist/internal/NativeProperties.js +2 -0
  259. package/dist/internal/NativeProperties.js.map +1 -0
  260. package/dist/internal/Numeric.d.ts +23 -0
  261. package/dist/internal/Numeric.d.ts.map +1 -0
  262. package/dist/internal/Numeric.js +2 -0
  263. package/dist/internal/Numeric.js.map +1 -0
  264. package/dist/internal/Query.d.ts +15 -0
  265. package/dist/internal/Query.d.ts.map +1 -0
  266. package/dist/internal/Query.js +58 -0
  267. package/dist/internal/Query.js.map +1 -0
  268. package/dist/internal/Recipe.d.ts +17 -0
  269. package/dist/internal/Recipe.d.ts.map +1 -0
  270. package/dist/internal/Recipe.js +2 -0
  271. package/dist/internal/Recipe.js.map +1 -0
  272. package/dist/internal/RuleReference.d.ts +23 -0
  273. package/dist/internal/RuleReference.d.ts.map +1 -0
  274. package/dist/internal/RuleReference.js +65 -0
  275. package/dist/internal/RuleReference.js.map +1 -0
  276. package/dist/internal/Scheme.d.ts +12 -0
  277. package/dist/internal/Scheme.d.ts.map +1 -0
  278. package/dist/internal/Scheme.js +16 -0
  279. package/dist/internal/Scheme.js.map +1 -0
  280. package/dist/internal/Shorthands.d.ts +20 -0
  281. package/dist/internal/Shorthands.d.ts.map +1 -0
  282. package/dist/internal/Shorthands.js +49 -0
  283. package/dist/internal/Shorthands.js.map +1 -0
  284. package/dist/internal/Targets.d.ts +43 -0
  285. package/dist/internal/Targets.d.ts.map +1 -0
  286. package/dist/internal/Targets.js +60 -0
  287. package/dist/internal/Targets.js.map +1 -0
  288. package/dist/internal/Token.d.ts +104 -0
  289. package/dist/internal/Token.d.ts.map +1 -0
  290. package/dist/internal/Token.js +162 -0
  291. package/dist/internal/Token.js.map +1 -0
  292. package/dist/internal/Tuple.d.ts +23 -0
  293. package/dist/internal/Tuple.d.ts.map +1 -0
  294. package/dist/internal/Tuple.js +2 -0
  295. package/dist/internal/Tuple.js.map +1 -0
  296. package/dist/internal/Value.d.ts +74 -0
  297. package/dist/internal/Value.d.ts.map +1 -0
  298. package/dist/internal/Value.js +60 -0
  299. package/dist/internal/Value.js.map +1 -0
  300. package/dist/metro/Graph.d.ts +8 -0
  301. package/dist/metro/Graph.d.ts.map +1 -0
  302. package/dist/metro/Graph.js +63 -0
  303. package/dist/metro/Graph.js.map +1 -0
  304. package/dist/metro/Watch.d.ts +21 -0
  305. package/dist/metro/Watch.d.ts.map +1 -0
  306. package/dist/metro/Watch.js +51 -0
  307. package/dist/metro/Watch.js.map +1 -0
  308. package/dist/metro/index.d.ts +30 -0
  309. package/dist/metro/index.d.ts.map +1 -0
  310. package/dist/metro/index.js +52 -0
  311. package/dist/metro/index.js.map +1 -0
  312. package/dist/metro/transformer.d.ts +21 -0
  313. package/dist/metro/transformer.d.ts.map +1 -0
  314. package/dist/metro/transformer.js +71 -0
  315. package/dist/metro/transformer.js.map +1 -0
  316. package/dist/next/index.d.ts +18 -0
  317. package/dist/next/index.d.ts.map +1 -0
  318. package/dist/next/index.js +92 -0
  319. package/dist/next/index.js.map +1 -0
  320. package/dist/next/loader.d.ts +16 -0
  321. package/dist/next/loader.d.ts.map +1 -0
  322. package/dist/next/loader.js +282 -0
  323. package/dist/next/loader.js.map +1 -0
  324. package/dist/node/Host.d.ts +80 -0
  325. package/dist/node/Host.d.ts.map +1 -0
  326. package/dist/node/Host.js +882 -0
  327. package/dist/node/Host.js.map +1 -0
  328. package/dist/node/index.d.ts +7 -0
  329. package/dist/node/index.d.ts.map +1 -0
  330. package/dist/node/index.js +7 -0
  331. package/dist/node/index.js.map +1 -0
  332. package/dist/react-native/Host.d.ts +76 -0
  333. package/dist/react-native/Host.d.ts.map +1 -0
  334. package/dist/react-native/Host.js +209 -0
  335. package/dist/react-native/Host.js.map +1 -0
  336. package/dist/react-native/StyleSheet.d.ts +226 -0
  337. package/dist/react-native/StyleSheet.d.ts.map +1 -0
  338. package/dist/react-native/StyleSheet.js +606 -0
  339. package/dist/react-native/StyleSheet.js.map +1 -0
  340. package/dist/react-native/Variants.d.ts +38 -0
  341. package/dist/react-native/Variants.d.ts.map +1 -0
  342. package/dist/react-native/Variants.js +66 -0
  343. package/dist/react-native/Variants.js.map +1 -0
  344. package/dist/react-native/index.d.ts +8 -0
  345. package/dist/react-native/index.d.ts.map +1 -0
  346. package/dist/react-native/index.js +8 -0
  347. package/dist/react-native/index.js.map +1 -0
  348. package/dist/react-native/internal/Color.d.ts +7 -0
  349. package/dist/react-native/internal/Color.d.ts.map +1 -0
  350. package/dist/react-native/internal/Color.js +93 -0
  351. package/dist/react-native/internal/Color.js.map +1 -0
  352. package/dist/react-native/internal/NativeSchema.d.ts +5138 -0
  353. package/dist/react-native/internal/NativeSchema.d.ts.map +1 -0
  354. package/dist/react-native/internal/NativeSchema.js +3097 -0
  355. package/dist/react-native/internal/NativeSchema.js.map +1 -0
  356. package/dist/react-native/internal/Scalar.d.ts +95 -0
  357. package/dist/react-native/internal/Scalar.d.ts.map +1 -0
  358. package/dist/react-native/internal/Scalar.js +199 -0
  359. package/dist/react-native/internal/Scalar.js.map +1 -0
  360. package/dist/react-native/internal/Values.d.ts +5 -0
  361. package/dist/react-native/internal/Values.d.ts.map +1 -0
  362. package/dist/react-native/internal/Values.js +65 -0
  363. package/dist/react-native/internal/Values.js.map +1 -0
  364. package/dist/react-native/react.d.ts +22 -0
  365. package/dist/react-native/react.d.ts.map +1 -0
  366. package/dist/react-native/react.js +26 -0
  367. package/dist/react-native/react.js.map +1 -0
  368. package/dist/reset.css +244 -0
  369. package/dist/runtime/Appearance.d.ts +55 -0
  370. package/dist/runtime/Appearance.d.ts.map +1 -0
  371. package/dist/runtime/Appearance.js +84 -0
  372. package/dist/runtime/Appearance.js.map +1 -0
  373. package/dist/runtime/Composition.d.ts +46 -0
  374. package/dist/runtime/Composition.d.ts.map +1 -0
  375. package/dist/runtime/Composition.js +52 -0
  376. package/dist/runtime/Composition.js.map +1 -0
  377. package/dist/runtime/CompositionHtml.d.ts +15 -0
  378. package/dist/runtime/CompositionHtml.d.ts.map +1 -0
  379. package/dist/runtime/CompositionHtml.js +20 -0
  380. package/dist/runtime/CompositionHtml.js.map +1 -0
  381. package/dist/runtime/ConditionalRecipe.d.ts +30 -0
  382. package/dist/runtime/ConditionalRecipe.d.ts.map +1 -0
  383. package/dist/runtime/ConditionalRecipe.js +39 -0
  384. package/dist/runtime/ConditionalRecipe.js.map +1 -0
  385. package/dist/runtime/Dynamic.d.ts +19 -0
  386. package/dist/runtime/Dynamic.d.ts.map +1 -0
  387. package/dist/runtime/Dynamic.js +22 -0
  388. package/dist/runtime/Dynamic.js.map +1 -0
  389. package/dist/runtime/Html.d.ts +32 -0
  390. package/dist/runtime/Html.d.ts.map +1 -0
  391. package/dist/runtime/Html.js +63 -0
  392. package/dist/runtime/Html.js.map +1 -0
  393. package/dist/runtime/Native.d.ts +48 -0
  394. package/dist/runtime/Native.d.ts.map +1 -0
  395. package/dist/runtime/Native.js +78 -0
  396. package/dist/runtime/Native.js.map +1 -0
  397. package/dist/runtime/NativeContext.d.ts +17 -0
  398. package/dist/runtime/NativeContext.d.ts.map +1 -0
  399. package/dist/runtime/NativeContext.js +47 -0
  400. package/dist/runtime/NativeContext.js.map +1 -0
  401. package/dist/runtime/NativeDynamic.d.ts +47 -0
  402. package/dist/runtime/NativeDynamic.d.ts.map +1 -0
  403. package/dist/runtime/NativeDynamic.js +141 -0
  404. package/dist/runtime/NativeDynamic.js.map +1 -0
  405. package/dist/runtime/PayloadRecipe.d.ts +22 -0
  406. package/dist/runtime/PayloadRecipe.d.ts.map +1 -0
  407. package/dist/runtime/PayloadRecipe.js +59 -0
  408. package/dist/runtime/PayloadRecipe.js.map +1 -0
  409. package/dist/runtime/Props.d.ts +21 -0
  410. package/dist/runtime/Props.d.ts.map +1 -0
  411. package/dist/runtime/Props.js +17 -0
  412. package/dist/runtime/Props.js.map +1 -0
  413. package/dist/runtime/Recipe.d.ts +52 -0
  414. package/dist/runtime/Recipe.d.ts.map +1 -0
  415. package/dist/runtime/Recipe.js +30 -0
  416. package/dist/runtime/Recipe.js.map +1 -0
  417. package/dist/runtime/Selection.d.ts +31 -0
  418. package/dist/runtime/Selection.d.ts.map +1 -0
  419. package/dist/runtime/Selection.js +30 -0
  420. package/dist/runtime/Selection.js.map +1 -0
  421. package/dist/runtime/Variable.d.ts +6 -0
  422. package/dist/runtime/Variable.d.ts.map +1 -0
  423. package/dist/runtime/Variable.js +10 -0
  424. package/dist/runtime/Variable.js.map +1 -0
  425. package/dist/runtime/index.d.ts +33 -0
  426. package/dist/runtime/index.d.ts.map +1 -0
  427. package/dist/runtime/index.js +33 -0
  428. package/dist/runtime/index.js.map +1 -0
  429. package/dist/styleFunction.d.ts +72 -0
  430. package/dist/styleFunction.d.ts.map +1 -0
  431. package/dist/styleFunction.js +18 -0
  432. package/dist/styleFunction.js.map +1 -0
  433. package/dist/themes/LICENSE.tailwind +21 -0
  434. package/dist/variable.d.ts +50 -0
  435. package/dist/variable.d.ts.map +1 -0
  436. package/dist/variable.js +20 -0
  437. package/dist/variable.js.map +1 -0
  438. package/dist/variants.d.ts +84 -0
  439. package/dist/variants.d.ts.map +1 -0
  440. package/dist/variants.js +21 -0
  441. package/dist/variants.js.map +1 -0
  442. package/dist/vite/index.d.ts +24 -0
  443. package/dist/vite/index.d.ts.map +1 -0
  444. package/dist/vite/index.js +1089 -0
  445. package/dist/vite/index.js.map +1 -0
  446. package/dist/web/Css.d.ts +81 -0
  447. package/dist/web/Css.d.ts.map +1 -0
  448. package/dist/web/Css.js +593 -0
  449. package/dist/web/Css.js.map +1 -0
  450. package/dist/web/colorProfile.d.ts +28 -0
  451. package/dist/web/colorProfile.d.ts.map +1 -0
  452. package/dist/web/colorProfile.js +8 -0
  453. package/dist/web/colorProfile.js.map +1 -0
  454. package/dist/web/counterStyle.d.ts +48 -0
  455. package/dist/web/counterStyle.d.ts.map +1 -0
  456. package/dist/web/counterStyle.js +8 -0
  457. package/dist/web/counterStyle.js.map +1 -0
  458. package/dist/web/cssFunction.d.ts +80 -0
  459. package/dist/web/cssFunction.d.ts.map +1 -0
  460. package/dist/web/cssFunction.js +18 -0
  461. package/dist/web/cssFunction.js.map +1 -0
  462. package/dist/web/customMedia.d.ts +12 -0
  463. package/dist/web/customMedia.d.ts.map +1 -0
  464. package/dist/web/customMedia.js +7 -0
  465. package/dist/web/customMedia.js.map +1 -0
  466. package/dist/web/fontFace.d.ts +26 -0
  467. package/dist/web/fontFace.d.ts.map +1 -0
  468. package/dist/web/fontFace.js +7 -0
  469. package/dist/web/fontFace.js.map +1 -0
  470. package/dist/web/fontFeatureValues.d.ts +40 -0
  471. package/dist/web/fontFeatureValues.d.ts.map +1 -0
  472. package/dist/web/fontFeatureValues.js +7 -0
  473. package/dist/web/fontFeatureValues.js.map +1 -0
  474. package/dist/web/fontPaletteValues.d.ts +21 -0
  475. package/dist/web/fontPaletteValues.d.ts.map +1 -0
  476. package/dist/web/fontPaletteValues.js +9 -0
  477. package/dist/web/fontPaletteValues.js.map +1 -0
  478. package/dist/web/global.d.ts +19 -0
  479. package/dist/web/global.d.ts.map +1 -0
  480. package/dist/web/global.js +6 -0
  481. package/dist/web/global.js.map +1 -0
  482. package/dist/web/importCss.d.ts +18 -0
  483. package/dist/web/importCss.d.ts.map +1 -0
  484. package/dist/web/importCss.js +7 -0
  485. package/dist/web/importCss.js.map +1 -0
  486. package/dist/web/index.d.ts +22 -0
  487. package/dist/web/index.d.ts.map +1 -0
  488. package/dist/web/index.js +22 -0
  489. package/dist/web/index.js.map +1 -0
  490. package/dist/web/internal/Block.d.ts +18 -0
  491. package/dist/web/internal/Block.d.ts.map +1 -0
  492. package/dist/web/internal/Block.js +13 -0
  493. package/dist/web/internal/Block.js.map +1 -0
  494. package/dist/web/internal/ClassName.d.ts +19 -0
  495. package/dist/web/internal/ClassName.d.ts.map +1 -0
  496. package/dist/web/internal/ClassName.js +77 -0
  497. package/dist/web/internal/ClassName.js.map +1 -0
  498. package/dist/web/internal/Context.d.ts +11 -0
  499. package/dist/web/internal/Context.d.ts.map +1 -0
  500. package/dist/web/internal/Context.js +2 -0
  501. package/dist/web/internal/Context.js.map +1 -0
  502. package/dist/web/internal/Contributions.d.ts +70 -0
  503. package/dist/web/internal/Contributions.d.ts.map +1 -0
  504. package/dist/web/internal/Contributions.js +109 -0
  505. package/dist/web/internal/Contributions.js.map +1 -0
  506. package/dist/web/internal/Namespace.d.ts +13 -0
  507. package/dist/web/internal/Namespace.d.ts.map +1 -0
  508. package/dist/web/internal/Namespace.js +13 -0
  509. package/dist/web/internal/Namespace.js.map +1 -0
  510. package/dist/web/internal/Themes.d.ts +13 -0
  511. package/dist/web/internal/Themes.d.ts.map +1 -0
  512. package/dist/web/internal/Themes.js +96 -0
  513. package/dist/web/internal/Themes.js.map +1 -0
  514. package/dist/web/keyframes.d.ts +14 -0
  515. package/dist/web/keyframes.d.ts.map +1 -0
  516. package/dist/web/keyframes.js +8 -0
  517. package/dist/web/keyframes.js.map +1 -0
  518. package/dist/web/layers.d.ts +4 -0
  519. package/dist/web/layers.d.ts.map +1 -0
  520. package/dist/web/layers.js +7 -0
  521. package/dist/web/layers.js.map +1 -0
  522. package/dist/web/namespace.d.ts +14 -0
  523. package/dist/web/namespace.d.ts.map +1 -0
  524. package/dist/web/namespace.js +7 -0
  525. package/dist/web/namespace.js.map +1 -0
  526. package/dist/web/page.d.ts +38 -0
  527. package/dist/web/page.d.ts.map +1 -0
  528. package/dist/web/page.js +7 -0
  529. package/dist/web/page.js.map +1 -0
  530. package/dist/web/positionTry.d.ts +14 -0
  531. package/dist/web/positionTry.d.ts.map +1 -0
  532. package/dist/web/positionTry.js +9 -0
  533. package/dist/web/positionTry.js.map +1 -0
  534. package/dist/web/property.d.ts +24 -0
  535. package/dist/web/property.d.ts.map +1 -0
  536. package/dist/web/property.js +7 -0
  537. package/dist/web/property.js.map +1 -0
  538. package/dist/web/viewTransition.d.ts +29 -0
  539. package/dist/web/viewTransition.d.ts.map +1 -0
  540. package/dist/web/viewTransition.js +7 -0
  541. package/dist/web/viewTransition.js.map +1 -0
  542. package/package.json +136 -10
  543. package/src/Config.ts +690 -0
  544. package/src/Props.ts +8 -0
  545. package/src/Style.ts +748 -0
  546. package/src/Theme.ts +713 -0
  547. package/src/babel/NativeEdits.ts +273 -0
  548. package/src/babel/NativeJsx.ts +260 -0
  549. package/src/babel/index.ts +332 -0
  550. package/src/cli/index.ts +196 -0
  551. package/src/compiler/Graph.ts +1586 -0
  552. package/src/compiler/Native.ts +801 -0
  553. package/src/compiler/Source.ts +1550 -0
  554. package/src/compiler/Transform.ts +1235 -0
  555. package/src/compiler/index.ts +12 -0
  556. package/src/compiler/internal/Applications.ts +378 -0
  557. package/src/compiler/internal/AtRules.ts +202 -0
  558. package/src/compiler/internal/Catalogs.ts +114 -0
  559. package/src/compiler/internal/ColorProfiles.ts +93 -0
  560. package/src/compiler/internal/CompositionBindings.ts +120 -0
  561. package/src/compiler/internal/Compositions.ts +629 -0
  562. package/src/compiler/internal/Configurations.ts +244 -0
  563. package/src/compiler/internal/Contract.ts +846 -0
  564. package/src/compiler/internal/Contributions.ts +1507 -0
  565. package/src/compiler/internal/Descriptors.ts +238 -0
  566. package/src/compiler/internal/Dynamic.ts +266 -0
  567. package/src/compiler/internal/Edits.ts +13 -0
  568. package/src/compiler/internal/Expression.ts +135 -0
  569. package/src/compiler/internal/Functions.ts +206 -0
  570. package/src/compiler/internal/Identifiers.ts +124 -0
  571. package/src/compiler/internal/Keyframes.ts +62 -0
  572. package/src/compiler/internal/Namespaces.ts +296 -0
  573. package/src/compiler/internal/NativeBindings.ts +151 -0
  574. package/src/compiler/internal/PackedStyles.ts +464 -0
  575. package/src/compiler/internal/Properties.ts +121 -0
  576. package/src/compiler/internal/RecipeConditions.ts +139 -0
  577. package/src/compiler/internal/RecipePayloads.ts +132 -0
  578. package/src/compiler/internal/Recipes.ts +531 -0
  579. package/src/compiler/internal/Relative.ts +87 -0
  580. package/src/compiler/internal/Scope.ts +36 -0
  581. package/src/compiler/internal/Selectors.ts +334 -0
  582. package/src/compiler/internal/Static.ts +783 -0
  583. package/src/compiler/internal/Stylesheets.ts +361 -0
  584. package/src/compiler/internal/Syntax.ts +31 -0
  585. package/src/compiler/internal/Themes.ts +1794 -0
  586. package/src/compiler/internal/Variables.ts +497 -0
  587. package/src/compiler/internal/ViewTransitions.ts +82 -0
  588. package/src/cx.ts +98 -0
  589. package/src/default.ts +484 -0
  590. package/src/index.ts +20 -0
  591. package/src/internal/Authoring.ts +199 -0
  592. package/src/internal/Binding.ts +187 -0
  593. package/src/internal/BindingDomains.ts +458 -0
  594. package/src/internal/Cascade.ts +165 -0
  595. package/src/internal/Compound.ts +522 -0
  596. package/src/internal/Condition.ts +283 -0
  597. package/src/internal/Corner.ts +17 -0
  598. package/src/internal/FunctionSyntax.ts +271 -0
  599. package/src/internal/FunctionValue.ts +96 -0
  600. package/src/internal/Geometry.ts +30 -0
  601. package/src/internal/Grid.ts +67 -0
  602. package/src/internal/Identifier.ts +14 -0
  603. package/src/internal/Identity.ts +89 -0
  604. package/src/internal/Lexical.ts +202 -0
  605. package/src/internal/Literal.ts +3820 -0
  606. package/src/internal/NativeProperties.ts +936 -0
  607. package/src/internal/Numeric.ts +77 -0
  608. package/src/internal/Query.ts +87 -0
  609. package/src/internal/Recipe.ts +17 -0
  610. package/src/internal/RuleReference.ts +102 -0
  611. package/src/internal/Scheme.ts +20 -0
  612. package/src/internal/Shorthands.ts +120 -0
  613. package/src/internal/Targets.ts +162 -0
  614. package/src/internal/Token.ts +380 -0
  615. package/src/internal/Tuple.ts +29 -0
  616. package/src/internal/Value.ts +320 -0
  617. package/src/metro/Graph.ts +78 -0
  618. package/src/metro/Watch.ts +88 -0
  619. package/src/metro/index.ts +99 -0
  620. package/src/metro/transformer.ts +97 -0
  621. package/src/next/index.ts +114 -0
  622. package/src/next/loader.ts +369 -0
  623. package/src/node/Host.ts +1204 -0
  624. package/src/node/index.ts +6 -0
  625. package/src/react-native/Host.ts +289 -0
  626. package/src/react-native/StyleSheet.ts +1084 -0
  627. package/src/react-native/Variants.ts +122 -0
  628. package/src/react-native/index.ts +7 -0
  629. package/src/react-native/internal/Color.ts +110 -0
  630. package/src/react-native/internal/NativeSchema.ts +3096 -0
  631. package/src/react-native/internal/Scalar.ts +253 -0
  632. package/src/react-native/internal/Values.ts +87 -0
  633. package/src/react-native/react.ts +47 -0
  634. package/src/reset.css +244 -0
  635. package/src/runtime/Appearance.ts +155 -0
  636. package/src/runtime/Composition.ts +87 -0
  637. package/src/runtime/CompositionHtml.ts +38 -0
  638. package/src/runtime/ConditionalRecipe.ts +70 -0
  639. package/src/runtime/Dynamic.ts +51 -0
  640. package/src/runtime/Html.ts +91 -0
  641. package/src/runtime/Native.ts +144 -0
  642. package/src/runtime/NativeContext.ts +74 -0
  643. package/src/runtime/NativeDynamic.ts +246 -0
  644. package/src/runtime/PayloadRecipe.ts +96 -0
  645. package/src/runtime/Props.ts +33 -0
  646. package/src/runtime/Recipe.ts +74 -0
  647. package/src/runtime/Selection.ts +82 -0
  648. package/src/runtime/Variable.ts +15 -0
  649. package/src/runtime/index.ts +45 -0
  650. package/src/styleFunction.ts +138 -0
  651. package/src/themes/LICENSE.tailwind +21 -0
  652. package/src/variable.ts +105 -0
  653. package/src/variants.ts +218 -0
  654. package/src/vite/index.ts +1473 -0
  655. package/src/web/Css.ts +801 -0
  656. package/src/web/colorProfile.ts +60 -0
  657. package/src/web/counterStyle.ts +82 -0
  658. package/src/web/cssFunction.ts +181 -0
  659. package/src/web/customMedia.ts +16 -0
  660. package/src/web/fontFace.ts +41 -0
  661. package/src/web/fontFeatureValues.ts +79 -0
  662. package/src/web/fontPaletteValues.ts +42 -0
  663. package/src/web/global.ts +39 -0
  664. package/src/web/importCss.ts +23 -0
  665. package/src/web/index.ts +22 -0
  666. package/src/web/internal/Block.ts +29 -0
  667. package/src/web/internal/ClassName.ts +112 -0
  668. package/src/web/internal/Context.ts +16 -0
  669. package/src/web/internal/Contributions.ts +219 -0
  670. package/src/web/internal/Namespace.ts +21 -0
  671. package/src/web/internal/Themes.ts +133 -0
  672. package/src/web/keyframes.ts +43 -0
  673. package/src/web/layers.ts +6 -0
  674. package/src/web/namespace.ts +19 -0
  675. package/src/web/page.ts +140 -0
  676. package/src/web/positionTry.ts +71 -0
  677. package/src/web/property.ts +35 -0
  678. package/src/web/viewTransition.ts +89 -0
@@ -0,0 +1,1204 @@
1
+ /**
2
+ * Processes standalone CSS and publishes incremental file builds with watch recovery.
3
+ * @module
4
+ */
5
+ import * as Mapping from '@jridgewell/gen-mapping'
6
+ import type * as LightningCss from 'lightningcss'
7
+ import * as Crypto from 'node:crypto'
8
+ import * as NativeFs from 'node:fs'
9
+ import * as Fs from 'node:fs/promises'
10
+ import * as Path from 'node:path'
11
+ import { ResolverFactory } from 'oxc-resolver'
12
+ import * as Graph from '../compiler/Graph.js'
13
+ import * as AtRules from '../compiler/internal/AtRules.js'
14
+ import * as Catalogs from '../compiler/internal/Catalogs.js'
15
+ import * as Relative from '../compiler/internal/Relative.js'
16
+ import * as Syntax from '../compiler/internal/Syntax.js'
17
+ import * as Source from '../compiler/Source.js'
18
+ import * as Transform from '../compiler/Transform.js'
19
+
20
+ /** A successful publication; paths are relative to the output directory. */
21
+ export type Build = {
22
+ /** Written or removed artifacts, excluding the ownership manifest. */
23
+ readonly changed: readonly string[]
24
+ /** Complete live artifact list, excluding the ownership manifest. */
25
+ readonly files: readonly string[]
26
+ }
27
+
28
+ /**
29
+ * Opens an exclusively owned output lifecycle around the literal source transform.
30
+ * Source modules remain TypeScript/JSX; transpilation belongs to the consumer.
31
+ * Besides per-module stylesheets, every build publishes `zyzz.css`: shared
32
+ * contributions followed by module stylesheets with dependencies before their
33
+ * consumers, so an application loads one file. Configurations also publish
34
+ * `zyzz.js`, the initialization that restores a saved theme and scheme, at
35
+ * the configurable script path.
36
+ * Lightning CSS processes stylesheets and composes maps before publication by default.
37
+ * @param options - Source directory, separate output directory, and portable package identity.
38
+ * @returns Explicit build, watch, and close operations. Close releases the output lock.
39
+ */
40
+ export async function create(options: create.Options): Promise<Runtime> {
41
+ type Stylesheet = { code: string; map: string }
42
+
43
+ const css =
44
+ options.css === false
45
+ ? false
46
+ : {
47
+ minify: options.css?.minify ?? false,
48
+ targets: { ...options.css?.targets },
49
+ }
50
+
51
+ const native = options.native
52
+ ? Object.freeze({
53
+ ...options.native,
54
+ fonts:
55
+ options.native.fonts && Object.freeze({ ...options.native.fonts }),
56
+ // Theme definitions are immutable. Only the caller-owned catalog needs copying.
57
+ themes:
58
+ options.native.themes && Object.freeze({ ...options.native.themes }),
59
+ units:
60
+ options.native.units && Object.freeze({ ...options.native.units }),
61
+ })
62
+ : undefined
63
+
64
+ if (native && (options.compiler === false || options.modules === false))
65
+ throw new Error('Native builds require rewritten module output.')
66
+
67
+ const outDir = Path.resolve(options.outDir ?? 'dist')
68
+ const root = await Fs.realpath(options.root)
69
+
70
+ if (inside(outDir, root))
71
+ throw new Error('Output must not contain the source directory.')
72
+
73
+ // A script inside the output is an owned artifact; elsewhere it is rewritten
74
+ // in place so a bundler's public directory can serve it verbatim.
75
+ const script = (() => {
76
+ if (native || options.script === false) return undefined
77
+
78
+ const path = Path.resolve(options.script ?? Path.join(outDir, 'zyzz.js'))
79
+
80
+ if (path !== outDir && inside(outDir, path))
81
+ return { owned: Path.relative(outDir, path).split(Path.sep).join('/') }
82
+ if (inside(root, path))
83
+ throw new Error(
84
+ 'The script path must not be inside the source directory.',
85
+ )
86
+
87
+ return { external: path }
88
+ })()
89
+
90
+ Transform.compile({
91
+ moduleId: `${options.packageId}/identity.ts`,
92
+ source: '',
93
+ })
94
+
95
+ await Fs.mkdir(outDir, { recursive: true })
96
+
97
+ if ((await Fs.realpath(outDir)) !== outDir)
98
+ throw new Error('Output paths must not contain symbolic links.')
99
+
100
+ const lockPath = Path.join(outDir, '.zyzz-lock')
101
+ const lock = await Fs.open(lockPath, 'wx')
102
+
103
+ // Probe the actual output filesystem using the already exclusively owned lock.
104
+ const insensitive = await (async () => {
105
+ try {
106
+ const alternate = await Fs.stat(Path.join(outDir, '.ZYZZ-LOCK'))
107
+ const original = await lock.stat()
108
+
109
+ return alternate.dev === original.dev && alternate.ino === original.ino
110
+ } catch (error) {
111
+ if (
112
+ error &&
113
+ typeof error === 'object' &&
114
+ 'code' in error &&
115
+ error.code === 'ENOENT'
116
+ )
117
+ return false
118
+
119
+ await lock.close()
120
+ await Fs.rm(lockPath)
121
+ throw error
122
+ }
123
+ })()
124
+
125
+ const manifestPath = Path.join(outDir, '.zyzz.json')
126
+
127
+ const compiler = Graph.create()
128
+ const stylesheets = new WeakMap<Transform.compile.ReturnType, Stylesheet>()
129
+ let closed = false
130
+ let closing: Promise<void> | undefined
131
+ let tail: Promise<void> = Promise.resolve()
132
+ const watchers = new Map<
133
+ string,
134
+ { inode: number; watcher: NativeFs.FSWatcher }
135
+ >()
136
+ let watching = false
137
+
138
+ type Dependency = {
139
+ inode?: number | undefined
140
+ listener: (current: NativeFs.Stats, previous: NativeFs.Stats) => void
141
+ watcher?: NativeFs.FSWatcher | undefined
142
+ }
143
+ const dependencies = new Map<string, Dependency>()
144
+ let invalidate: (() => void) | undefined
145
+ let previousContracts = new Set<string>()
146
+ let previousImports: Record<string, Record<string, string | null>> = {}
147
+ let report: ((error: unknown) => void) | undefined
148
+
149
+ async function perform(): Promise<Build> {
150
+ const observed = new Set<string>()
151
+
152
+ function observe(path: string, directory = false) {
153
+ observed.add(path)
154
+ if (!watching || closed) return
155
+
156
+ let dependency = dependencies.get(path)
157
+ if (!dependency) {
158
+ const listener = (
159
+ current: NativeFs.Stats,
160
+ previous: NativeFs.Stats,
161
+ ) => {
162
+ if (
163
+ current.ino !== previous.ino ||
164
+ current.dev !== previous.dev ||
165
+ current.mtimeMs !== previous.mtimeMs ||
166
+ current.ctimeMs !== previous.ctimeMs
167
+ )
168
+ invalidate?.()
169
+ }
170
+ dependency = { listener }
171
+ dependencies.set(path, dependency)
172
+ // Path polling survives removal, atomic replacement, and symlink retargeting.
173
+ NativeFs.watchFile(path, { interval: 250, persistent: false }, listener)
174
+ }
175
+ if (!directory) return
176
+
177
+ const status = NativeFs.statSync(path, { throwIfNoEntry: false })
178
+ if (status?.ino === dependency.inode) return
179
+
180
+ dependency.watcher?.close()
181
+ dependency.watcher = undefined
182
+ dependency.inode = status?.ino
183
+ if (!status?.isDirectory()) return
184
+
185
+ const real = NativeFs.realpathSync(path)
186
+ dependency.watcher = NativeFs.watch(
187
+ path,
188
+ { recursive: true },
189
+ (_event, filename) => {
190
+ if (filename && inside(outDir, Path.join(real, filename.toString())))
191
+ return
192
+ if (
193
+ filename &&
194
+ /(?:^|[/\\])(?:node_modules|\.git)(?:[/\\]|$)/.test(
195
+ filename.toString(),
196
+ )
197
+ )
198
+ return
199
+ invalidate?.()
200
+ },
201
+ )
202
+ dependency.watcher.on('error', (error) => {
203
+ dependency.inode = undefined
204
+ report?.(error)
205
+ })
206
+ }
207
+
208
+ const inputs: string[] = []
209
+
210
+ async function scan(directory: string) {
211
+ for (const entry of await Fs.readdir(directory, {
212
+ withFileTypes: true,
213
+ })) {
214
+ const path = Path.join(directory, entry.name)
215
+ if (
216
+ inside(outDir, path) ||
217
+ entry.name === '.git' ||
218
+ [
219
+ 'node_modules',
220
+ 'test',
221
+ 'tests',
222
+ '__tests__',
223
+ 'fixtures',
224
+ '__fixtures__',
225
+ ].includes(entry.name)
226
+ )
227
+ continue
228
+
229
+ if (entry.isDirectory()) await scan(path)
230
+ else if (
231
+ entry.isFile() &&
232
+ /\.[cm]?[jt]sx?$/.test(entry.name) &&
233
+ !/\.(?:d|test|test-d|bench)\.[cm]?[jt]sx?$/.test(entry.name)
234
+ )
235
+ inputs.push(path)
236
+ }
237
+ }
238
+
239
+ await scan(root)
240
+ inputs.sort()
241
+
242
+ const artifacts = new Map<string, string | Uint8Array>()
243
+ const sources: Record<string, string> = Object.create(null)
244
+
245
+ for (const input of inputs) {
246
+ const name = Path.relative(root, input).split(Path.sep).join('/')
247
+ if (
248
+ ['.zyzz-lock', '.zyzz.json'].includes(name.split('/')[0]!.toLowerCase())
249
+ )
250
+ throw new Error(
251
+ `Source path conflicts with host control files: ${name}`,
252
+ )
253
+
254
+ sources[name] = await Fs.readFile(input, 'utf8')
255
+ }
256
+
257
+ const modules = Object.fromEntries(
258
+ Object.entries(sources).map(([name, source]) => [
259
+ `${options.packageId}/${name}`,
260
+ source,
261
+ ]),
262
+ )
263
+ const contracts: Record<string, string> = Object.create(null)
264
+ const imports: Record<
265
+ string,
266
+ Record<string, string | null>
267
+ > = Object.create(null)
268
+ // A build gets fresh package metadata, including changed export maps.
269
+ const resolver = new ResolverFactory({
270
+ builtinModules: true,
271
+ conditionNames: ['node', 'import'],
272
+ nodePath: false,
273
+ })
274
+
275
+ function resolve(specifier: string, importer: string): string | undefined {
276
+ const packageName = specifier.startsWith('@')
277
+ ? specifier.split('/').slice(0, 2).join('/')
278
+ : specifier.split('/')[0]!
279
+ for (let directory = Path.dirname(importer); ; ) {
280
+ observe(Path.join(directory, 'package.json'))
281
+ observe(Path.join(directory, 'node_modules'))
282
+ if (
283
+ !specifier.startsWith('.') &&
284
+ !specifier.startsWith('#') &&
285
+ !Path.isAbsolute(specifier)
286
+ )
287
+ observe(Path.join(directory, 'node_modules', packageName), true)
288
+ const parent = Path.dirname(directory)
289
+ if (parent === directory) break
290
+ directory = parent
291
+ }
292
+ const resolved = resolver.sync(Path.dirname(importer), specifier)
293
+
294
+ if (resolved.builtin) return undefined
295
+ if (!resolved.path)
296
+ throw new Error(
297
+ `Unable to resolve ${JSON.stringify(specifier)} from ${importer}: ${resolved.error}`,
298
+ )
299
+
300
+ observe(resolved.path)
301
+ if (resolved.packageJsonPath) observe(resolved.packageJsonPath)
302
+ return resolved.path
303
+ }
304
+
305
+ async function contract(file: string, required = false): Promise<boolean> {
306
+ if (Object.hasOwn(contracts, file)) return true
307
+
308
+ observe(`${file}.zyzz.json`)
309
+ try {
310
+ contracts[file] = await Fs.readFile(`${file}.zyzz.json`, 'utf8')
311
+ } catch (error) {
312
+ if (
313
+ !required &&
314
+ !previousContracts.has(file) &&
315
+ (error as NodeJS.ErrnoException).code === 'ENOENT'
316
+ )
317
+ return false
318
+ throw error
319
+ }
320
+
321
+ const metadata = (() => {
322
+ try {
323
+ return JSON.parse(contracts[file]!) as {
324
+ stylesheets?: { dependency?: string[] }[]
325
+ }
326
+ } catch (error) {
327
+ Graph.compile({
328
+ modules: {},
329
+ contracts: { [file]: contracts[file]! },
330
+ })
331
+ throw error
332
+ }
333
+ })()
334
+
335
+ if (!Array.isArray(metadata?.stylesheets)) return true
336
+
337
+ for (const section of metadata.stylesheets) {
338
+ if (!Array.isArray(section?.dependency)) continue
339
+
340
+ let owner = file
341
+ for (const specifier of section.dependency) {
342
+ if (
343
+ typeof specifier !== 'string' ||
344
+ !specifier ||
345
+ specifier.includes('\0')
346
+ )
347
+ throw new Error('Invalid packed stylesheet dependency.')
348
+
349
+ const target = resolve(specifier, owner)
350
+ if (!target)
351
+ throw new Error('Unable to resolve packed stylesheet dependency.')
352
+
353
+ ;(imports[owner] ??= Object.create(null))[specifier] = target
354
+ await contract(target, true)
355
+ owner = target
356
+ }
357
+ }
358
+
359
+ return true
360
+ }
361
+
362
+ for (const [name, source] of Object.entries(sources)) {
363
+ const moduleId = `${options.packageId}/${name}`
364
+ const file = Path.join(root, name)
365
+ const resolutions = (imports[moduleId] = Object.create(null))
366
+
367
+ for (const node of Syntax.parse({ moduleId, source }).program.body) {
368
+ if (
369
+ (node.type !== 'ImportDeclaration' &&
370
+ node.type !== 'ExportNamedDeclaration' &&
371
+ node.type !== 'ExportAllDeclaration') ||
372
+ !node.source
373
+ )
374
+ continue
375
+
376
+ const specifier = node.source.value
377
+ resolutions[specifier] = null
378
+ if (
379
+ node.type === 'ImportDeclaration'
380
+ ? node.importKind === 'type'
381
+ : node.exportKind === 'type'
382
+ )
383
+ continue
384
+ if (
385
+ 'specifiers' in node &&
386
+ node.specifiers.length &&
387
+ node.specifiers.every((specifier) =>
388
+ specifier.type === 'ImportSpecifier'
389
+ ? specifier.importKind === 'type'
390
+ : specifier.type === 'ExportSpecifier' &&
391
+ specifier.exportKind === 'type',
392
+ )
393
+ )
394
+ continue
395
+ if (
396
+ specifier === 'zyzz' ||
397
+ (specifier.startsWith('zyzz/') && specifier !== 'zyzz/default')
398
+ )
399
+ continue
400
+ if (
401
+ /^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(specifier) ||
402
+ specifier.includes('?') ||
403
+ (!specifier.startsWith('#') && specifier.includes('#'))
404
+ )
405
+ continue
406
+ try {
407
+ if (specifier.startsWith('.')) {
408
+ const target = Relative.resolve({ moduleId, modules, specifier })
409
+ if (target) resolutions[specifier] = target
410
+ continue
411
+ }
412
+
413
+ const target = resolve(specifier, file)
414
+ if (!target) continue
415
+ const relative = Path.relative(root, target).split(Path.sep).join('/')
416
+ if (Object.hasOwn(sources, relative))
417
+ resolutions[specifier] = `${options.packageId}/${relative}`
418
+ else if (/\.[cm]?[jt]sx?$/.test(target)) {
419
+ const previous = previousImports[moduleId]?.[specifier]
420
+ if (
421
+ await contract(
422
+ target,
423
+ !!previous && previousContracts.has(previous),
424
+ )
425
+ )
426
+ resolutions[specifier] = target
427
+ }
428
+ } catch (error) {
429
+ throw new Source.ExtractError([
430
+ {
431
+ code: 'unsupported_syntax',
432
+ source: moduleId,
433
+ start: node.start,
434
+ end: node.end,
435
+ message: (error as Error).message,
436
+ },
437
+ ])
438
+ }
439
+ }
440
+ }
441
+
442
+ const graph = compiler.compile({
443
+ compiler: options.compiler,
444
+ native,
445
+ modules,
446
+ contracts,
447
+ imports,
448
+ })
449
+
450
+ const artifactNames = [
451
+ 'zyzz.css',
452
+ 'zyzz.css.map',
453
+ 'zyzz.shared.css',
454
+ 'zyzz.shared.css.map',
455
+ '.zyzz.json',
456
+ '.zyzz-lock',
457
+ ...Object.keys(sources).flatMap((name) => [
458
+ name,
459
+ `${name}.map`,
460
+ `${name}.css`,
461
+ `${name}.css.map`,
462
+ `${name}.zyzz.json`,
463
+ ]),
464
+ ].map((name) => (insensitive ? name.toLowerCase() : name))
465
+
466
+ // The script is one more owned artifact, so it must not replace another.
467
+ if (
468
+ script?.owned &&
469
+ artifactNames.includes(
470
+ insensitive ? script.owned.toLowerCase() : script.owned,
471
+ )
472
+ )
473
+ throw new Error(
474
+ `The script path collides with the artifact ${script.owned}.`,
475
+ )
476
+
477
+ const generated = new Set([
478
+ ...(script?.owned ? [script.owned] : []),
479
+ ...artifactNames,
480
+ ])
481
+
482
+ let shared: Stylesheet | undefined
483
+
484
+ if (graph.sharedCss) {
485
+ const assets = new Map<string, string>()
486
+ function relocate(
487
+ url: LightningCss.Url,
488
+ target = graph.sharedAssets?.[url.url],
489
+ ) {
490
+ if (!target) return
491
+ if (!target.startsWith(`${options.packageId}/`))
492
+ throw new Error('Asset path escapes the package root.')
493
+ const relative = target.slice(options.packageId.length + 1)
494
+ const decoded = decodeURIComponent(relative.split(/[?#]/)[0]!)
495
+ const filename = Path.posix.normalize(decoded)
496
+ if (
497
+ filename === '..' ||
498
+ filename.startsWith('../') ||
499
+ filename.startsWith('/') ||
500
+ filename.includes('\\') ||
501
+ filename.includes('\0') ||
502
+ filename.includes(':')
503
+ )
504
+ throw new Error('Asset path escapes the package root.')
505
+ if (
506
+ filename.split('/').some((_, index, parts) => {
507
+ const ancestor = parts.slice(0, index + 1).join('/')
508
+ return generated.has(
509
+ insensitive ? ancestor.toLowerCase() : ancestor,
510
+ )
511
+ })
512
+ )
513
+ throw new Error('Asset path conflicts with generated output.')
514
+ if (
515
+ filename
516
+ .split('/')
517
+ .some((part) =>
518
+ ['.zyzz.json', '.zyzz-lock'].includes(part.toLowerCase()),
519
+ )
520
+ )
521
+ throw new Error('Asset path conflicts with host control files.')
522
+ assets.set(filename, Path.join(root, filename))
523
+ return {
524
+ ...url,
525
+ url:
526
+ filename.split('/').map(encodeURIComponent).join('/') +
527
+ relative.slice(relative.split(/[?#]/)[0]!.length),
528
+ }
529
+ }
530
+
531
+ const processed =
532
+ css === false && !Object.keys(graph.sharedAssets ?? {}).length
533
+ ? {
534
+ code: Buffer.from(graph.sharedCss),
535
+ map: Buffer.from(JSON.stringify(graph.sharedCssMap)),
536
+ }
537
+ : AtRules.transform({
538
+ filename: 'zyzz.shared.css',
539
+ code: Buffer.from(graph.sharedCss),
540
+ sourceMap: true,
541
+ inputSourceMap: JSON.stringify(graph.sharedCssMap),
542
+ minify: css === false ? false : css.minify,
543
+ ...(css === false ? {} : { targets: css.targets }),
544
+ visitor: {
545
+ Rule(rule) {
546
+ if (rule.type !== 'import') return
547
+ const url = relocate({
548
+ url: rule.value.url,
549
+ loc: rule.value.loc,
550
+ })
551
+ if (url) return AtRules.relocateImport(rule.value, url.url)
552
+ },
553
+ Url: relocate,
554
+ },
555
+ })
556
+
557
+ for (const [name, file] of assets) {
558
+ const real = await Fs.realpath(file)
559
+ if (!inside(root, real))
560
+ throw new Error('Asset path escapes the package root.')
561
+ const content = await Fs.readFile(real)
562
+ if (name.endsWith('.css')) {
563
+ function discover(url: string) {
564
+ if (!url || /^(?:\/|[?#]|[a-z][a-z\d+.-]*:)/i.test(url)) return
565
+ const target = `${options.packageId}/${Path.posix.join(Path.posix.dirname(name), url)}`
566
+ relocate({ url, loc: { line: 1, column: 1 } }, target)
567
+ }
568
+ AtRules.transform({
569
+ filename: name,
570
+ code: content,
571
+ visitor: {
572
+ Rule(rule) {
573
+ if (rule.type === 'import') discover(rule.value.url)
574
+ },
575
+ Url(url) {
576
+ discover(url.url)
577
+ },
578
+ },
579
+ })
580
+ }
581
+ artifacts.set(name, content)
582
+ }
583
+
584
+ shared = {
585
+ code: Buffer.from(processed.code).toString(),
586
+ map: Buffer.from(processed.map!).toString(),
587
+ }
588
+
589
+ artifacts.set('zyzz.shared.css', shared.code)
590
+ artifacts.set('zyzz.shared.css.map', shared.map)
591
+ }
592
+
593
+ const moduleStylesheets = new Map<string, Stylesheet>()
594
+
595
+ for (const name of Object.keys(sources)) {
596
+ const output = graph.modules[`${options.packageId}/${name}`]!
597
+
598
+ const contract = graph.contracts[`${options.packageId}/${name}`]
599
+
600
+ if (options.modules !== false) {
601
+ if (contract) artifacts.set(`${name}.zyzz.json`, contract)
602
+ artifacts.set(name, output.code)
603
+ artifacts.set(`${name}.map`, JSON.stringify(output.map))
604
+ }
605
+
606
+ if (native) continue
607
+
608
+ let stylesheet = stylesheets.get(output)
609
+
610
+ if (!stylesheet) {
611
+ if (css === false)
612
+ stylesheet = { code: output.css, map: JSON.stringify(output.cssMap) }
613
+ else {
614
+ const result = AtRules.transform({
615
+ code: Buffer.from(output.css),
616
+ filename: `${options.packageId}/${name}.css`,
617
+ inputSourceMap: JSON.stringify(output.cssMap),
618
+ minify: css.minify,
619
+ sourceMap: true,
620
+ targets: css.targets,
621
+ })
622
+
623
+ stylesheet = {
624
+ code: Buffer.from(result.code).toString(),
625
+ map: Buffer.from(result.map!).toString(),
626
+ }
627
+ }
628
+
629
+ stylesheets.set(output, stylesheet)
630
+ }
631
+
632
+ artifacts.set(`${name}.css`, stylesheet.code)
633
+ artifacts.set(`${name}.css.map`, stylesheet.map)
634
+ // Module URLs resolve beside the module file; the complete stylesheet at
635
+ // the output root carries a copy with those URLs rebased.
636
+ moduleStylesheets.set(
637
+ `${options.packageId}/${name}`,
638
+ rebase(stylesheet, name, css === false ? false : css.minify),
639
+ )
640
+ }
641
+
642
+ // The complete stylesheet follows the module graph so a consumer's rules
643
+ // cascade over the rules of the modules it imports.
644
+ if (shared || moduleStylesheets.size) {
645
+ const complete = concatenate([
646
+ ...(shared ? [shared] : []),
647
+ ...order(graph.dependencies, [...moduleStylesheets.keys()]).map(
648
+ (id) => moduleStylesheets.get(id)!,
649
+ ),
650
+ ])
651
+
652
+ artifacts.set('zyzz.css', complete.code)
653
+ artifacts.set('zyzz.css.map', complete.map)
654
+ }
655
+
656
+ // Every configuration in the tree restores its saved selection from one script.
657
+ const initialization = Catalogs.scripts(
658
+ Object.values({ ...contracts, ...graph.contracts }).flatMap(
659
+ Catalogs.read,
660
+ ),
661
+ ).join('\n')
662
+
663
+ const content = initialization ? `${banner}${initialization}\n` : undefined
664
+
665
+ if (script?.owned && content) artifacts.set(script.owned, content)
666
+
667
+ // An external script has no ownership record. Its leading banner marks
668
+ // output this host may replace or remove; any other file there is foreign.
669
+ const external = await (async () => {
670
+ if (!script?.external) return undefined
671
+
672
+ const current = await read(script.external)
673
+
674
+ if (current !== undefined && !current.startsWith(banner))
675
+ throw new Error(
676
+ `Refusing to replace a foreign script: ${script.external}`,
677
+ )
678
+
679
+ return { current, next: content, path: script.external }
680
+ })()
681
+
682
+ await regular(manifestPath, outDir)
683
+
684
+ const previous = await read(manifestPath)
685
+ const owned =
686
+ previous === undefined ? {} : manifest(previous, options.packageId)
687
+ const key = (name: string) => (insensitive ? name.toLowerCase() : name)
688
+ const ownedNames = new Map(
689
+ Object.keys(owned).map((name) => [key(name), name]),
690
+ )
691
+ const liveNames = new Map<string, string>()
692
+
693
+ for (const name of artifacts.keys()) {
694
+ if (liveNames.has(key(name)))
695
+ throw new Error(`Output paths differ only in case: ${name}`)
696
+
697
+ liveNames.set(key(name), name)
698
+ }
699
+
700
+ const hashes: Record<string, string> = Object.create(null)
701
+ const before = new Map<string, string | Uint8Array | undefined>()
702
+ const changed: string[] = []
703
+
704
+ for (const name of new Set([...Object.keys(owned), ...artifacts.keys()])) {
705
+ // A case-only rename still owns the same physical file. Do not delete its old alias.
706
+ if (!artifacts.has(name) && liveNames.has(key(name))) continue
707
+
708
+ const owner = ownedNames.get(key(name))
709
+ const path = Path.join(outDir, name)
710
+
711
+ await regular(path, outDir)
712
+
713
+ const content = await read(path, true)
714
+ const expected = owner === undefined ? undefined : owned[owner]
715
+ if (
716
+ content !== undefined &&
717
+ (expected === undefined || hash(content) !== expected)
718
+ )
719
+ throw new Error(
720
+ `Refusing to replace an unowned or modified output: ${name}`,
721
+ )
722
+
723
+ const next = artifacts.get(name)
724
+
725
+ if (next !== undefined) hashes[name] = hash(next)
726
+
727
+ if (
728
+ (content === undefined || next === undefined
729
+ ? content !== next
730
+ : hash(content) !== hash(next)) ||
731
+ (owner !== undefined && owner !== name)
732
+ ) {
733
+ before.set(name, content)
734
+ changed.push(name)
735
+ }
736
+ }
737
+
738
+ const nextManifest = JSON.stringify({
739
+ files: hashes,
740
+ packageId: options.packageId,
741
+ version: 1,
742
+ })
743
+
744
+ if (nextManifest !== previous) before.set('.zyzz.json', previous)
745
+
746
+ // Compile and verify ownership before publishing. Restore applied writes if publication fails.
747
+ const applied: string[] = []
748
+ let externalApplied = false
749
+
750
+ async function place(
751
+ path: string,
752
+ content: string | Uint8Array | undefined,
753
+ ) {
754
+ if (content === undefined) await Fs.rm(path, { force: true })
755
+ else await write(path, content)
756
+ }
757
+
758
+ try {
759
+ for (const [name] of before) {
760
+ const content =
761
+ name === '.zyzz.json' ? nextManifest : artifacts.get(name)
762
+
763
+ applied.push(name)
764
+ await place(Path.join(outDir, name), content)
765
+ }
766
+
767
+ // The external script joins the transaction so a rejected build leaves it untouched.
768
+ if (external && external.next !== external.current) {
769
+ externalApplied = true
770
+ await place(external.path, external.next)
771
+ }
772
+ } catch (error) {
773
+ // The external path may stay unwritable, which must not skip the owned rollback.
774
+ if (externalApplied)
775
+ await place(external!.path, external!.current).catch(() => {})
776
+
777
+ for (const name of applied.reverse())
778
+ await place(Path.join(outDir, name), before.get(name))
779
+
780
+ throw error
781
+ }
782
+
783
+ previousContracts = new Set(Object.keys(contracts))
784
+ previousImports = imports
785
+ for (const [path, dependency] of dependencies) {
786
+ if (observed.has(path)) continue
787
+ NativeFs.unwatchFile(path, dependency.listener)
788
+ dependency.watcher?.close()
789
+ dependencies.delete(path)
790
+ }
791
+
792
+ return { changed: changed.sort(), files: [...artifacts.keys()].sort() }
793
+ }
794
+
795
+ function build(): Promise<Build> {
796
+ if (closed) return Promise.reject(new Error('Host is closed.'))
797
+
798
+ const pending = tail.then(perform)
799
+
800
+ tail = pending.then(
801
+ () => {},
802
+ () => {},
803
+ )
804
+
805
+ return pending
806
+ }
807
+
808
+ function close(): Promise<void> {
809
+ if (closing) return closing
810
+
811
+ closed = true
812
+ for (const { watcher } of watchers.values()) watcher.close()
813
+ watchers.clear()
814
+ for (const [path, dependency] of dependencies) {
815
+ NativeFs.unwatchFile(path, dependency.listener)
816
+ dependency.watcher?.close()
817
+ }
818
+ dependencies.clear()
819
+
820
+ closing = (async () => {
821
+ await tail
822
+ await lock.close()
823
+ await Fs.rm(lockPath)
824
+ })()
825
+
826
+ return closing
827
+ }
828
+
829
+ function watch(watchOptions: watch.Options) {
830
+ if (closed) throw new Error('Host is closed.')
831
+ if (watching) throw new Error('Host is already watching.')
832
+ watching = true
833
+ report = (error) => {
834
+ if (!closed) watchOptions.onResult({ error })
835
+ }
836
+
837
+ let dirty = false
838
+ let running = false
839
+ invalidate = () => {
840
+ dirty = true
841
+ void flush()
842
+ }
843
+
844
+ async function flush() {
845
+ if (running) return
846
+
847
+ running = true
848
+
849
+ try {
850
+ while (dirty && !closed) {
851
+ dirty = false
852
+
853
+ const seen = new Set<string>()
854
+ const event: Event = await directories(root, seen)
855
+ .then(() => {
856
+ for (const [directory, { watcher }] of watchers)
857
+ if (!seen.has(directory)) {
858
+ watcher.close()
859
+ watchers.delete(directory)
860
+ }
861
+ })
862
+ .then(() => build())
863
+ .then(
864
+ (result) => ({ result }),
865
+ (error: unknown) => ({ error }),
866
+ )
867
+
868
+ if (!closed) watchOptions.onResult(event)
869
+ }
870
+ } finally {
871
+ running = false
872
+ }
873
+ }
874
+
875
+ async function directories(
876
+ directory: string,
877
+ seen: Set<string>,
878
+ ): Promise<void> {
879
+ if (closed || inside(outDir, directory)) return
880
+ // Watch directories rather than file inodes, which atomic editor saves replace.
881
+ const status = await Fs.stat(directory).catch(
882
+ (error: NodeJS.ErrnoException) => {
883
+ if (error.code !== 'ENOENT') throw error
884
+ return undefined
885
+ },
886
+ )
887
+ if (closed) return
888
+ if (status) seen.add(directory)
889
+ if (!status || watchers.get(directory)?.inode !== status.ino) {
890
+ watchers.get(directory)?.watcher.close()
891
+ watchers.delete(directory)
892
+ }
893
+ if (!status) return
894
+ if (!watchers.has(directory)) {
895
+ const watcher = NativeFs.watch(directory, () => {
896
+ dirty = true
897
+ void flush()
898
+ })
899
+ watcher.on('error', (error) => watchOptions.onResult({ error }))
900
+ watchers.set(directory, { inode: status.ino, watcher })
901
+ }
902
+ const entries = await Fs.readdir(directory, {
903
+ withFileTypes: true,
904
+ }).catch((error: NodeJS.ErrnoException) => {
905
+ if (error.code !== 'ENOENT') throw error
906
+ watchers.get(directory)?.watcher.close()
907
+ watchers.delete(directory)
908
+ return []
909
+ })
910
+ for (const entry of entries)
911
+ if (
912
+ entry.isDirectory() &&
913
+ !['.git', 'node_modules'].includes(entry.name)
914
+ )
915
+ await directories(Path.join(directory, entry.name), seen)
916
+ }
917
+
918
+ dirty = true
919
+ void flush()
920
+ }
921
+
922
+ return { [Symbol.asyncDispose]: close, build, close, watch }
923
+ }
924
+
925
+ /** File host creation contracts. */
926
+ export declare namespace create {
927
+ /** Explicit filesystem and module-identity boundaries. */
928
+ type Options = {
929
+ /** Rewrite source calls. False requires runtime-compatible explicit identities. */
930
+ readonly compiler?: boolean | undefined
931
+ /** Publish rewritten modules and metadata alongside CSS. Defaults to true. */
932
+ readonly modules?: boolean | undefined
933
+ /** Lightning CSS processing; false preserves intermediate CSS. Enabled by default. */
934
+ readonly css?:
935
+ | false
936
+ | {
937
+ /** Minify emitted stylesheets. Defaults to false. */
938
+ readonly minify?: boolean | undefined
939
+ /** Lightning CSS browser versions, encoded as major << 16 | minor << 8 | patch. No targets by default. */
940
+ readonly targets?: Readonly<LightningCss.Targets> | undefined
941
+ }
942
+ | undefined
943
+ /** Native context captured at creation. Emits modules and maps without CSS or web initialization. */
944
+ readonly native?: Graph.compile.Options['native']
945
+ /** Output directory exclusively locked until close; may be nested under root. Defaults to `dist`. */
946
+ readonly outDir?: string | undefined
947
+ /** Stable package identity prepended to relative source module IDs. */
948
+ readonly packageId: string
949
+ /** Directory scanned for supported JavaScript/TypeScript source files. */
950
+ readonly root: string
951
+ /**
952
+ * Path of the initialization script restoring saved theme selections.
953
+ * Defaults to `zyzz.js` inside the output directory, where it is an owned
954
+ * artifact. A path elsewhere, such as a bundler's public directory, is
955
+ * rewritten in place without ownership. False disables the script.
956
+ */
957
+ readonly script?: string | false | undefined
958
+ }
959
+ }
960
+
961
+ /** Watch builds report failures without discarding the last successful output. */
962
+ export type Event = { readonly error: unknown } | { readonly result: Build }
963
+
964
+ /** An explicitly disposed file host. */
965
+ export type Runtime = {
966
+ /** Stops watching, drains builds, and releases ownership when an await using scope exits. */
967
+ readonly [Symbol.asyncDispose]: () => Promise<void>
968
+ /** Serializes a complete scan, compile, and publication; failures reject. */
969
+ readonly build: () => Promise<Build>
970
+ /** Stops watching, drains builds, and releases ownership. Idempotent. */
971
+ readonly close: () => Promise<void>
972
+ /** Starts recursive filesystem watching and an initial build. */
973
+ readonly watch: (options: watch.Options) => void
974
+ }
975
+
976
+ /** Watch notification contracts. */
977
+ export declare namespace watch {
978
+ /** Callback ownership remains with the host consumer. */
979
+ type Options = {
980
+ /** Receives successful builds and failures; must not throw. */
981
+ readonly onResult: (event: Event) => void
982
+ }
983
+ }
984
+
985
+ /** Leading comment marking initialization scripts this host wrote. */
986
+ const banner = '/* zyzz initialization */\n'
987
+
988
+ /** Joins processed stylesheets and shifts their composed maps by the preceding line count. */
989
+ function concatenate(parts: readonly { code: string; map: string }[]) {
990
+ const map = new Mapping.GenMapping({ file: 'zyzz.css' })
991
+ const chunks: string[] = []
992
+ let offset = 0
993
+
994
+ for (const part of parts) {
995
+ if (!part.code) continue
996
+
997
+ const code = part.code.endsWith('\n') ? part.code : `${part.code}\n`
998
+ const traced = Mapping.fromMap(part.map)
999
+
1000
+ for (const mapping of Mapping.allMappings(traced)) {
1001
+ const generated = {
1002
+ column: mapping.generated.column,
1003
+ line: mapping.generated.line + offset,
1004
+ }
1005
+
1006
+ if (mapping.source !== undefined && mapping.original !== undefined) {
1007
+ const location = {
1008
+ generated,
1009
+ original: mapping.original,
1010
+ source: mapping.source,
1011
+ }
1012
+
1013
+ if (mapping.name === undefined) Mapping.addMapping(map, location)
1014
+ else Mapping.addMapping(map, { ...location, name: mapping.name })
1015
+ } else Mapping.addMapping(map, { generated })
1016
+ }
1017
+
1018
+ const encoded = Mapping.toEncodedMap(traced)
1019
+
1020
+ for (const [index, source] of encoded.sources.entries())
1021
+ if (source !== null)
1022
+ Mapping.setSourceContent(
1023
+ map,
1024
+ source,
1025
+ encoded.sourcesContent?.[index] ?? null,
1026
+ )
1027
+
1028
+ chunks.push(code)
1029
+ offset += code.split('\n').length - 1
1030
+ }
1031
+
1032
+ return {
1033
+ code: chunks.join(''),
1034
+ map: JSON.stringify(Mapping.toEncodedMap(map)),
1035
+ }
1036
+ }
1037
+
1038
+ function hash(content: string | Uint8Array) {
1039
+ return Crypto.createHash('sha256').update(content).digest('hex')
1040
+ }
1041
+
1042
+ function inside(parent: string, child: string) {
1043
+ const relative = Path.relative(parent, child)
1044
+
1045
+ return (
1046
+ !relative ||
1047
+ (!relative.startsWith(`..${Path.sep}`) &&
1048
+ relative !== '..' &&
1049
+ !Path.isAbsolute(relative))
1050
+ )
1051
+ }
1052
+
1053
+ function manifest(source: string, packageId: string): Record<string, string> {
1054
+ const value: unknown = JSON.parse(source)
1055
+ if (
1056
+ !value ||
1057
+ typeof value !== 'object' ||
1058
+ !('packageId' in value) ||
1059
+ value.packageId !== packageId ||
1060
+ !('version' in value) ||
1061
+ value.version !== 1 ||
1062
+ !('files' in value) ||
1063
+ !value.files ||
1064
+ typeof value.files !== 'object' ||
1065
+ Array.isArray(value.files)
1066
+ )
1067
+ throw new Error('Invalid output ownership manifest.')
1068
+
1069
+ for (const [path, digest] of Object.entries(value.files))
1070
+ if (
1071
+ !path ||
1072
+ path.includes('\\') ||
1073
+ path.includes(':') ||
1074
+ path.split('/').some((part) => !part || part === '.' || part === '..') ||
1075
+ typeof digest !== 'string' ||
1076
+ !/^[a-f0-9]{64}$/.test(digest) ||
1077
+ ['.zyzz-lock', '.zyzz.json'].includes(path.split('/')[0]!.toLowerCase())
1078
+ )
1079
+ throw new Error('Invalid owned output path or digest.')
1080
+
1081
+ return value.files as Record<string, string>
1082
+ }
1083
+
1084
+ /** Orders module identities with dependencies before their consumers, seeded from graph roots. */
1085
+ function order(
1086
+ dependencies: Readonly<Record<string, readonly string[]>>,
1087
+ ids: readonly string[],
1088
+ ) {
1089
+ const members = new Set(ids)
1090
+ const ordered: string[] = []
1091
+ const seen = new Set<string>()
1092
+
1093
+ function visit(id: string) {
1094
+ if (seen.has(id)) return
1095
+
1096
+ seen.add(id)
1097
+
1098
+ for (const dependency of dependencies[id] ?? [])
1099
+ if (members.has(dependency)) visit(dependency)
1100
+
1101
+ ordered.push(id)
1102
+ }
1103
+
1104
+ // Graph roots seed the traversal so siblings keep their authored import
1105
+ // order; modules only reachable through cycles follow in name order.
1106
+ const imported = new Set(
1107
+ ids.flatMap((id) =>
1108
+ (dependencies[id] ?? []).filter((dependency) => members.has(dependency)),
1109
+ ),
1110
+ )
1111
+
1112
+ for (const id of ids) if (!imported.has(id)) visit(id)
1113
+ for (const id of ids) visit(id)
1114
+
1115
+ return ordered
1116
+ }
1117
+
1118
+ async function read(path: string): Promise<string | undefined>
1119
+ async function read(path: string, binary: true): Promise<Uint8Array | undefined>
1120
+ async function read(
1121
+ path: string,
1122
+ binary = false,
1123
+ ): Promise<string | Uint8Array | undefined> {
1124
+ try {
1125
+ return binary ? await Fs.readFile(path) : await Fs.readFile(path, 'utf8')
1126
+ } catch (error) {
1127
+ if (
1128
+ error &&
1129
+ typeof error === 'object' &&
1130
+ 'code' in error &&
1131
+ error.code === 'ENOENT'
1132
+ )
1133
+ return undefined
1134
+
1135
+ throw error
1136
+ }
1137
+ }
1138
+
1139
+ /** Rewrites a nested module stylesheet's relative URLs against the output root. */
1140
+ function rebase(
1141
+ stylesheet: { code: string; map: string },
1142
+ name: string,
1143
+ minify: boolean,
1144
+ ) {
1145
+ const directory = Path.posix.dirname(name)
1146
+
1147
+ if (directory === '.' || !stylesheet.code.includes('url(')) return stylesheet
1148
+
1149
+ const result = AtRules.transform({
1150
+ code: Buffer.from(stylesheet.code),
1151
+ filename: `${name}.css`,
1152
+ inputSourceMap: stylesheet.map,
1153
+ minify,
1154
+ sourceMap: true,
1155
+ visitor: {
1156
+ Url(url) {
1157
+ if (/^(?:\/|[?#]|[a-z][a-z\d+.-]*:)/i.test(url.url)) return url
1158
+
1159
+ return { ...url, url: Path.posix.join(directory, url.url) }
1160
+ },
1161
+ },
1162
+ })
1163
+
1164
+ return {
1165
+ code: Buffer.from(result.code).toString(),
1166
+ map: Buffer.from(result.map!).toString(),
1167
+ }
1168
+ }
1169
+
1170
+ async function regular(path: string, root: string) {
1171
+ for (let current = path; current !== root; current = Path.dirname(current)) {
1172
+ try {
1173
+ const entry = await Fs.lstat(current)
1174
+ if (
1175
+ entry.isSymbolicLink() ||
1176
+ (current === path ? !entry.isFile() : !entry.isDirectory())
1177
+ )
1178
+ throw new Error('Output paths must be regular files and directories.')
1179
+ } catch (error) {
1180
+ if (
1181
+ !(
1182
+ error &&
1183
+ typeof error === 'object' &&
1184
+ 'code' in error &&
1185
+ error.code === 'ENOENT'
1186
+ )
1187
+ )
1188
+ throw error
1189
+ }
1190
+ }
1191
+ }
1192
+
1193
+ async function write(path: string, content: string | Uint8Array) {
1194
+ await Fs.mkdir(Path.dirname(path), { recursive: true })
1195
+
1196
+ const temporary = `${path}.${Crypto.randomUUID()}.tmp`
1197
+
1198
+ try {
1199
+ await Fs.writeFile(temporary, content, { flag: 'wx' })
1200
+ await Fs.rename(temporary, path)
1201
+ } finally {
1202
+ await Fs.rm(temporary, { force: true })
1203
+ }
1204
+ }