tungsten 0.3.1 → 0.3.3

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 (291) hide show
  1. package/dist/.build-complete +1 -0
  2. package/dist/Components.d.ts +2 -1
  3. package/dist/Components.d.ts.map +1 -1
  4. package/dist/Components.js +10 -1
  5. package/dist/DomRegion.js +1 -1
  6. package/dist/Framework.d.ts +2 -0
  7. package/dist/Framework.d.ts.map +1 -1
  8. package/dist/Framework.js +68 -57
  9. package/dist/FrameworkConfig.d.ts +6 -0
  10. package/dist/FrameworkConfig.d.ts.map +1 -1
  11. package/dist/FunctionComponentStandIn.d.ts +2 -0
  12. package/dist/FunctionComponentStandIn.d.ts.map +1 -1
  13. package/dist/FunctionComponentStandIn.js +10 -1
  14. package/dist/Instance/Instance.d.ts.map +1 -1
  15. package/dist/Instance/Instance.js +18 -1
  16. package/dist/Instance/InstanceConfig.d.ts +1 -0
  17. package/dist/Instance/InstanceConfig.d.ts.map +1 -1
  18. package/dist/PopMessage.type.d.ts +6 -0
  19. package/dist/PopMessage.type.d.ts.map +1 -0
  20. package/dist/PopMessage.type.js +1 -0
  21. package/dist/Servers/DevServer.d.ts +4 -0
  22. package/dist/Servers/DevServer.d.ts.map +1 -1
  23. package/dist/Servers/DevServer.js +116 -13
  24. package/dist/Servers/MatchedRouteInfo.d.ts +1 -1
  25. package/dist/Servers/MatchedRouteInfo.d.ts.map +1 -1
  26. package/dist/Servers/ProdServer.d.ts +1 -0
  27. package/dist/Servers/ProdServer.d.ts.map +1 -1
  28. package/dist/Servers/ProdServer.js +79 -5
  29. package/dist/Servers/devErrorPageAutoRetry.d.ts +4 -0
  30. package/dist/Servers/devErrorPageAutoRetry.d.ts.map +1 -0
  31. package/dist/Servers/devErrorPageAutoRetry.js +26 -0
  32. package/dist/Servers/hono/DevServerHono.js +25 -29
  33. package/dist/Servers/hono/ProdServerHono.js +49 -142
  34. package/dist/Servers/hono/TungstenServerHono.d.ts +1 -1
  35. package/dist/Servers/hono/TungstenServerHono.d.ts.map +1 -1
  36. package/dist/Servers/hono/TungstenServerHono.js +12 -29
  37. package/dist/Servers/routing.d.ts.map +1 -1
  38. package/dist/Servers/routing.js +10 -6
  39. package/dist/Servers/tungstenCorePrivateEnvSchema.d.ts +0 -3
  40. package/dist/Servers/tungstenCorePrivateEnvSchema.d.ts.map +1 -1
  41. package/dist/Servers/tungstenCorePrivateEnvSchema.js +3 -3
  42. package/dist/Servers/tungstenCorePublicEnvSchema.d.ts +8 -0
  43. package/dist/Servers/tungstenCorePublicEnvSchema.d.ts.map +1 -0
  44. package/dist/Servers/tungstenCorePublicEnvSchema.js +14 -0
  45. package/dist/Store/InternalStoreSchema.d.ts +2 -0
  46. package/dist/Store/InternalStoreSchema.d.ts.map +1 -1
  47. package/dist/Store/InternalStoreSchema.js +1 -0
  48. package/dist/api/Request.d.ts +1 -1
  49. package/dist/api/Request.d.ts.map +1 -1
  50. package/dist/api/Response.d.ts +1 -1
  51. package/dist/api/Response.d.ts.map +1 -1
  52. package/dist/api/getExport.d.ts.map +1 -1
  53. package/dist/api/getExport.js +2 -1
  54. package/dist/babelPlugins/BabelAddDevCacheBust.d.ts +11 -0
  55. package/dist/babelPlugins/BabelAddDevCacheBust.d.ts.map +1 -0
  56. package/dist/babelPlugins/BabelAddDevCacheBust.js +68 -0
  57. package/dist/babelPlugins/BabelTypes.d.ts +2 -2
  58. package/dist/babelPlugins/BabelTypes.d.ts.map +1 -1
  59. package/dist/babelPlugins/BabelTypes.js +0 -1
  60. package/dist/bin/commands/build.d.ts.map +1 -1
  61. package/dist/bin/commands/build.js +3 -0
  62. package/dist/bin/commands/dev.d.ts.map +1 -1
  63. package/dist/bin/commands/dev.js +16 -3
  64. package/dist/bin/commands/devmon.d.ts +2 -0
  65. package/dist/bin/commands/devmon.d.ts.map +1 -0
  66. package/dist/bin/commands/devmon.js +66 -0
  67. package/dist/bin/index.d.ts.map +1 -1
  68. package/dist/bin/index.js +6 -0
  69. package/dist/booleanAttributeValue.d.ts +21 -0
  70. package/dist/booleanAttributeValue.d.ts.map +1 -0
  71. package/dist/booleanAttributeValue.js +23 -0
  72. package/dist/build/compileJavascript.js +1 -1
  73. package/dist/build/compileUserApp.d.ts +2 -1
  74. package/dist/build/compileUserApp.d.ts.map +1 -1
  75. package/dist/build/compileUserApp.js +10 -9
  76. package/dist/build/createInstanceConfigFile.js +1 -1
  77. package/dist/build/makeBabelUserDevConfig.d.ts.map +1 -1
  78. package/dist/build/makeBabelUserDevConfig.js +6 -1
  79. package/dist/compat/types.d.ts +1 -1
  80. package/dist/compat/types.d.ts.map +1 -1
  81. package/dist/components/PopMessages.d.ts +12 -0
  82. package/dist/components/PopMessages.d.ts.map +1 -0
  83. package/dist/components/PopMessages.js +45 -0
  84. package/dist/defaultConfig.d.ts +3 -0
  85. package/dist/defaultConfig.d.ts.map +1 -1
  86. package/dist/defaultConfig.js +4 -1
  87. package/dist/env/Interfaces.d.ts +2 -1
  88. package/dist/env/Interfaces.d.ts.map +1 -1
  89. package/dist/env/getEnvSchemas.d.ts +1 -1
  90. package/dist/env/getEnvSchemas.d.ts.map +1 -1
  91. package/dist/env/getEnvSchemas.js +2 -1
  92. package/dist/env/publicEnv.d.ts.map +1 -1
  93. package/dist/env/publicEnv.js +4 -1
  94. package/dist/frameworkConfigSchema.d.ts +4 -0
  95. package/dist/frameworkConfigSchema.d.ts.map +1 -1
  96. package/dist/frameworkConfigSchema.js +2 -1
  97. package/dist/getComponent.d.ts.map +1 -1
  98. package/dist/getComponent.js +2 -1
  99. package/dist/getRoutes.d.ts.map +1 -1
  100. package/dist/getRoutes.js +2 -1
  101. package/dist/hmr/applyHmrModule.d.ts +11 -0
  102. package/dist/hmr/applyHmrModule.d.ts.map +1 -0
  103. package/dist/hmr/applyHmrModule.js +78 -0
  104. package/dist/hmr/componentIdentity.d.ts +9 -0
  105. package/dist/hmr/componentIdentity.d.ts.map +1 -0
  106. package/dist/hmr/componentIdentity.js +17 -0
  107. package/dist/hmr/instanceRegistry.d.ts +4 -0
  108. package/dist/hmr/instanceRegistry.d.ts.map +1 -0
  109. package/dist/hmr/instanceRegistry.js +6 -0
  110. package/dist/hmr/liveReloadHub.d.ts +10 -0
  111. package/dist/hmr/liveReloadHub.d.ts.map +1 -0
  112. package/dist/{dev → hmr}/liveReloadHub.js +8 -2
  113. package/dist/hmr/refreshStylesheets.d.ts +2 -0
  114. package/dist/hmr/refreshStylesheets.d.ts.map +1 -0
  115. package/dist/hmr/refreshStylesheets.js +26 -0
  116. package/dist/hooks/index.d.ts +1 -0
  117. package/dist/hooks/index.d.ts.map +1 -1
  118. package/dist/hooks/index.js +1 -0
  119. package/dist/hooks/useInstance.d.ts +3 -0
  120. package/dist/hooks/useInstance.d.ts.map +1 -0
  121. package/dist/hooks/useInstance.js +4 -0
  122. package/dist/hydrate/hydrate.d.ts +10 -0
  123. package/dist/hydrate/hydrate.d.ts.map +1 -1
  124. package/dist/hydrate/hydrate.js +81 -19
  125. package/dist/hydrate/reconcileHydratedAttributes.d.ts.map +1 -1
  126. package/dist/hydrate/reconcileHydratedAttributes.js +14 -5
  127. package/dist/hydrate/renderHydrationMismatchBanner.d.ts +7 -0
  128. package/dist/hydrate/renderHydrationMismatchBanner.d.ts.map +1 -0
  129. package/dist/hydrate/renderHydrationMismatchBanner.js +69 -0
  130. package/dist/importDevModuleWithRetry.d.ts +3 -0
  131. package/dist/importDevModuleWithRetry.d.ts.map +1 -0
  132. package/dist/importDevModuleWithRetry.js +46 -0
  133. package/dist/indexInner.d.ts +8 -0
  134. package/dist/indexInner.d.ts.map +1 -1
  135. package/dist/indexInner.js +7 -1
  136. package/dist/makeInstanceConfigFromFrameworkConfig.d.ts.map +1 -1
  137. package/dist/makeInstanceConfigFromFrameworkConfig.js +2 -1
  138. package/dist/pop.d.ts +10 -0
  139. package/dist/pop.d.ts.map +1 -0
  140. package/dist/pop.js +49 -0
  141. package/dist/rawHtml/filterContentNode.d.ts +20 -0
  142. package/dist/rawHtml/filterContentNode.d.ts.map +1 -0
  143. package/dist/rawHtml/filterContentNode.js +96 -0
  144. package/dist/rawHtml/parseHtml.d.ts +14 -0
  145. package/dist/rawHtml/parseHtml.d.ts.map +1 -1
  146. package/dist/rawHtml/parseHtml.js +4 -4
  147. package/dist/rawHtml/sanitizeHtml.d.ts +17 -0
  148. package/dist/rawHtml/sanitizeHtml.d.ts.map +1 -0
  149. package/dist/rawHtml/sanitizeHtml.js +19 -0
  150. package/dist/render/HeadData.d.ts +2 -0
  151. package/dist/render/HeadData.d.ts.map +1 -1
  152. package/dist/render/contentNodeToHtml.d.ts +18 -0
  153. package/dist/render/contentNodeToHtml.d.ts.map +1 -0
  154. package/dist/render/contentNodeToHtml.js +66 -0
  155. package/dist/render/contentToHtml.d.ts.map +1 -1
  156. package/dist/render/contentToHtml.js +3 -1
  157. package/dist/render/processHead.d.ts.map +1 -1
  158. package/dist/render/processHead.js +53 -6
  159. package/dist/render/renderingTreeToHtml.d.ts.map +1 -1
  160. package/dist/render/renderingTreeToHtml.js +8 -1
  161. package/dist/routing/ErrorRouteType.d.ts +6 -0
  162. package/dist/routing/ErrorRouteType.d.ts.map +1 -0
  163. package/dist/routing/ErrorRouteType.js +1 -0
  164. package/dist/routing/RouteTypes.d.ts +2 -1
  165. package/dist/routing/RouteTypes.d.ts.map +1 -1
  166. package/dist/routing/Routes.d.ts +5 -0
  167. package/dist/routing/Routes.d.ts.map +1 -1
  168. package/dist/routing/TungstenErrorInfo.d.ts +6 -0
  169. package/dist/routing/TungstenErrorInfo.d.ts.map +1 -0
  170. package/dist/routing/TungstenErrorInfo.js +6 -0
  171. package/dist/style/styleContentSxy.js +21 -0
  172. package/dist/testing/hydrateTestApp.d.ts +38 -0
  173. package/dist/testing/hydrateTestApp.d.ts.map +1 -0
  174. package/dist/testing/hydrateTestApp.js +242 -0
  175. package/dist/testing/index.d.ts +4 -3
  176. package/dist/testing/index.d.ts.map +1 -1
  177. package/dist/testing/index.js +16 -2
  178. package/dist/timeProfiler.d.ts +6 -0
  179. package/dist/timeProfiler.d.ts.map +1 -0
  180. package/dist/timeProfiler.js +31 -0
  181. package/dist/update/integrateUpdateVdom.d.ts +16 -1
  182. package/dist/update/integrateUpdateVdom.d.ts.map +1 -1
  183. package/dist/update/integrateUpdateVdom.js +116 -7
  184. package/dist/warnOnFrameworkChange.d.ts +2 -0
  185. package/dist/warnOnFrameworkChange.d.ts.map +1 -0
  186. package/dist/warnOnFrameworkChange.js +27 -0
  187. package/package.json +18 -16
  188. package/dist/Instance/gotoRedirect.sxyt.d.ts +0 -2
  189. package/dist/Instance/gotoRedirect.sxyt.d.ts.map +0 -1
  190. package/dist/Instance/gotoRedirect.sxyt.js +0 -148
  191. package/dist/Instance/runTrackedWork.sxyt.d.ts +0 -2
  192. package/dist/Instance/runTrackedWork.sxyt.d.ts.map +0 -1
  193. package/dist/Instance/runTrackedWork.sxyt.js +0 -35
  194. package/dist/_client/cjsHelpers.sxyt.d.ts +0 -2
  195. package/dist/_client/cjsHelpers.sxyt.d.ts.map +0 -1
  196. package/dist/_client/cjsHelpers.sxyt.js +0 -45
  197. package/dist/auth/passwordHashing.sxyt.d.ts +0 -2
  198. package/dist/auth/passwordHashing.sxyt.d.ts.map +0 -1
  199. package/dist/auth/passwordHashing.sxyt.js +0 -46
  200. package/dist/auth/ref/checkPasswordResetToken.sxyt.d.ts +0 -2
  201. package/dist/auth/ref/checkPasswordResetToken.sxyt.d.ts.map +0 -1
  202. package/dist/auth/ref/checkPasswordResetToken.sxyt.js +0 -40
  203. package/dist/auth/ref/createPasswordResetToken.sxyt.d.ts +0 -2
  204. package/dist/auth/ref/createPasswordResetToken.sxyt.d.ts.map +0 -1
  205. package/dist/auth/ref/createPasswordResetToken.sxyt.js +0 -10
  206. package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.d.ts +0 -2
  207. package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.d.ts.map +0 -1
  208. package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.js +0 -108
  209. package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.d.ts +0 -2
  210. package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.d.ts.map +0 -1
  211. package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.js +0 -104
  212. package/dist/bin/commands/compile.sxyt.d.ts +0 -2
  213. package/dist/bin/commands/compile.sxyt.d.ts.map +0 -1
  214. package/dist/bin/commands/compile.sxyt.js +0 -255
  215. package/dist/build/modifySassImports.sxyt.d.ts +0 -2
  216. package/dist/build/modifySassImports.sxyt.d.ts.map +0 -1
  217. package/dist/build/modifySassImports.sxyt.js +0 -55
  218. package/dist/build/sassImportParser.sxyt.d.ts +0 -2
  219. package/dist/build/sassImportParser.sxyt.d.ts.map +0 -1
  220. package/dist/build/sassImportParser.sxyt.js +0 -110
  221. package/dist/build/scssImportParserChatgpt.sxyt.d.ts +0 -2
  222. package/dist/build/scssImportParserChatgpt.sxyt.d.ts.map +0 -1
  223. package/dist/build/scssImportParserChatgpt.sxyt.js +0 -120
  224. package/dist/clone.sxyt.d.ts +0 -2
  225. package/dist/clone.sxyt.d.ts.map +0 -1
  226. package/dist/clone.sxyt.js +0 -24
  227. package/dist/componentProxyHandlers.sxyt.d.ts +0 -2
  228. package/dist/componentProxyHandlers.sxyt.d.ts.map +0 -1
  229. package/dist/componentProxyHandlers.sxyt.js +0 -130
  230. package/dist/components/RawHtml.sxyt.d.ts +0 -2
  231. package/dist/components/RawHtml.sxyt.d.ts.map +0 -1
  232. package/dist/components/RawHtml.sxyt.js +0 -104
  233. package/dist/components/bindable/BindableSelect.sxyt.d.ts +0 -2
  234. package/dist/components/bindable/BindableSelect.sxyt.d.ts.map +0 -1
  235. package/dist/components/bindable/BindableSelect.sxyt.js +0 -186
  236. package/dist/dev/liveReloadHub.d.ts +0 -6
  237. package/dist/dev/liveReloadHub.d.ts.map +0 -1
  238. package/dist/env/injectEnv.sxyt.d.ts +0 -2
  239. package/dist/env/injectEnv.sxyt.d.ts.map +0 -1
  240. package/dist/env/injectEnv.sxyt.js +0 -20
  241. package/dist/env/parseEnv.sxyt.d.ts +0 -2
  242. package/dist/env/parseEnv.sxyt.d.ts.map +0 -1
  243. package/dist/env/parseEnv.sxyt.js +0 -11
  244. package/dist/findProjectDir.sxyt.d.ts +0 -2
  245. package/dist/findProjectDir.sxyt.d.ts.map +0 -1
  246. package/dist/findProjectDir.sxyt.js +0 -82
  247. package/dist/hydrate/reconcileHydratedAttributes.sxyt.d.ts +0 -2
  248. package/dist/hydrate/reconcileHydratedAttributes.sxyt.d.ts.map +0 -1
  249. package/dist/hydrate/reconcileHydratedAttributes.sxyt.js +0 -173
  250. package/dist/innerHtmlFromProps.sxyt.d.ts +0 -2
  251. package/dist/innerHtmlFromProps.sxyt.d.ts.map +0 -1
  252. package/dist/innerHtmlFromProps.sxyt.js +0 -99
  253. package/dist/postcssPlugins/parseSelectors.sxyt.d.ts +0 -2
  254. package/dist/postcssPlugins/parseSelectors.sxyt.d.ts.map +0 -1
  255. package/dist/postcssPlugins/parseSelectors.sxyt.js +0 -62
  256. package/dist/postcssPlugins/parseSelectorsRich.sxyt.d.ts +0 -2
  257. package/dist/postcssPlugins/parseSelectorsRich.sxyt.d.ts.map +0 -1
  258. package/dist/postcssPlugins/parseSelectorsRich.sxyt.js +0 -155
  259. package/dist/rawHtml/parseHtml.sxyt.d.ts +0 -2
  260. package/dist/rawHtml/parseHtml.sxyt.d.ts.map +0 -1
  261. package/dist/rawHtml/parseHtml.sxyt.js +0 -239
  262. package/dist/render/getFunctionBodyAsString.sxyt.d.ts +0 -2
  263. package/dist/render/getFunctionBodyAsString.sxyt.d.ts.map +0 -1
  264. package/dist/render/getFunctionBodyAsString.sxyt.js +0 -37
  265. package/dist/render/processProps.sxyt.d.ts +0 -2
  266. package/dist/render/processProps.sxyt.d.ts.map +0 -1
  267. package/dist/render/processProps.sxyt.js +0 -90
  268. package/dist/routing/compareRequestToRegex.sxyt.d.ts +0 -2
  269. package/dist/routing/compareRequestToRegex.sxyt.d.ts.map +0 -1
  270. package/dist/routing/compareRequestToRegex.sxyt.js +0 -65
  271. package/dist/routing/getPathPriority.sxyt.d.ts +0 -2
  272. package/dist/routing/getPathPriority.sxyt.d.ts.map +0 -1
  273. package/dist/routing/getPathPriority.sxyt.js +0 -24
  274. package/dist/routing/matchPath.sxyt.d.ts +0 -2
  275. package/dist/routing/matchPath.sxyt.d.ts.map +0 -1
  276. package/dist/routing/matchPath.sxyt.js +0 -41
  277. package/dist/routing/patternToRegex.sxyt.d.ts +0 -2
  278. package/dist/routing/patternToRegex.sxyt.d.ts.map +0 -1
  279. package/dist/routing/patternToRegex.sxyt.js +0 -69
  280. package/dist/routing/splitRequest.sxyt.d.ts +0 -2
  281. package/dist/routing/splitRequest.sxyt.d.ts.map +0 -1
  282. package/dist/routing/splitRequest.sxyt.js +0 -47
  283. package/dist/style/jssToCss.sxyt.d.ts +0 -2
  284. package/dist/style/jssToCss.sxyt.d.ts.map +0 -1
  285. package/dist/style/jssToCss.sxyt.js +0 -17
  286. package/dist/testing/createTestApp.sxyt.d.ts +0 -2
  287. package/dist/testing/createTestApp.sxyt.d.ts.map +0 -1
  288. package/dist/testing/createTestApp.sxyt.js +0 -470
  289. package/dist/testing/ensureTestEnvLoaded.sxyt.d.ts +0 -2
  290. package/dist/testing/ensureTestEnvLoaded.sxyt.d.ts.map +0 -1
  291. package/dist/testing/ensureTestEnvLoaded.sxyt.js +0 -20
@@ -50,7 +50,8 @@ const frameworkConfigBaseValidator = arkType({
50
50
  'skipPackageCompilation?': 'string | string[]',
51
51
  'serverMiddleware?': ['string', 'string', 'string'],
52
52
  'apiRoutes?': 'string',
53
- 'apiPath?': 'string'
53
+ 'apiPath?': 'string',
54
+ 'csr?': 'boolean'
54
55
  });
55
56
  const frameworkConfigWithRootComponentValidator = arkType({
56
57
  '...': frameworkConfigBaseValidator,
@@ -1 +1 @@
1
- {"version":3,"file":"getComponent.d.ts","sourceRoot":"","sources":["../src/getComponent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAMhC,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAEhB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA6B3B"}
1
+ {"version":3,"file":"getComponent.d.ts","sourceRoot":"","sources":["../src/getComponent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAOhC,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAEhB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA6B3B"}
@@ -2,6 +2,7 @@ import { fixExtension } from "./fixExtension.js";
2
2
  import { TungstenError } from "./TungstenError.js";
3
3
  import { throwError } from "./throwError.js";
4
4
  import { iterationQueryString } from "./iterationQueryString.js";
5
+ import { importDevModuleWithRetry } from "./importDevModuleWithRetry.js";
5
6
  //let load //// !! future improvement
6
7
  export async function getComponent(filePath, filename,
7
8
  //load: Load | null = null,
@@ -16,7 +17,7 @@ iteration = null, mode = 'prod') {
16
17
  //const load = await createLoad(import.meta.url, sxyLoaderConfig)
17
18
  //console.log('load', filePath)
18
19
  //module = await load(filePath)
19
- module = await import(iterationQueryString(filePath, iteration));
20
+ module = await importDevModuleWithRetry(iterationQueryString(filePath, iteration));
20
21
  } else {
21
22
  //console.log('import', filePath)
22
23
  module = await import(filePath); // import the module
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAK5D,wBAAsB,SAAS,CAC3B,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,uBAAuB,EAE/B,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACnB,OAAO,CAAC,SAAS,CAAC,CAmCrB"}
1
+ {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAM5D,wBAAsB,SAAS,CAC3B,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,uBAAuB,EAE/B,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,IAAI,GAAE,IAAa,GACnB,OAAO,CAAC,SAAS,CAAC,CAmCrB"}
package/dist/getRoutes.js CHANGED
@@ -3,6 +3,7 @@ import { fixExtension } from "./fixExtension.js";
3
3
  import { TungstenError } from "./TungstenError.js";
4
4
  import { iterationQueryString } from "./iterationQueryString.js";
5
5
  import { throwError } from "./throwError.js";
6
+ import { importDevModuleWithRetry } from "./importDevModuleWithRetry.js";
6
7
  export async function getRoutes(compilationInfo, config,
7
8
  //load: Load | null = null,
8
9
  iteration = null, mode = 'prod') {
@@ -22,7 +23,7 @@ iteration = null, mode = 'prod') {
22
23
  // can we share load across the render?
23
24
  //const load = await createLoad(import.meta.url, sxyLoaderConfig)
24
25
  //module = await load(filePath)
25
- module = await import(iterationQueryString(filePath, iteration));
26
+ module = await importDevModuleWithRetry(iterationQueryString(filePath, iteration));
26
27
  } else {
27
28
  module = await import(filePath); // import the module
28
29
  }
@@ -0,0 +1,11 @@
1
+ export { refreshStylesheets } from './refreshStylesheets.js';
2
+ export type ApplyHmrModuleResult = {
3
+ matched: true;
4
+ count: number;
5
+ orphaned: boolean;
6
+ } | {
7
+ matched: false;
8
+ orphaned: boolean;
9
+ };
10
+ export declare function applyHmrModule(moduleExports: Record<string, unknown>, file?: string): Promise<ApplyHmrModuleResult>;
11
+ //# sourceMappingURL=applyHmrModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyHmrModule.d.ts","sourceRoot":"","sources":["../../src/hmr/applyHmrModule.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,MAAM,MAAM,oBAAoB,GAC1B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACnD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAA;AAsB3C,wBAAsB,cAAc,CAChC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GACtD,OAAO,CAAC,oBAAoB,CAAC,CAkD/B"}
@@ -0,0 +1,78 @@
1
+ import { AnyComponentIsFunctionComponentStandIn } from "../AnyComponent.js";
2
+ import { hotSwapClassComponent, hotSwapFunctionComponent } from "../update/integrateUpdateVdom.js";
3
+ import { componentTypeIdentityKey, componentTypeKind, liveComponentIdentityKey, liveComponentKind } from "./componentIdentity.js";
4
+ import { getCurrentInstance } from "./instanceRegistry.js";
5
+ export { refreshStylesheets } from "./refreshStylesheets.js";
6
+ function identityToken(kind, key) {
7
+ return `${kind}:${key}`;
8
+ }
9
+ function tokenKind(token) {
10
+ return token.startsWith('function:') ? 'function' : 'class';
11
+ }
12
+ function tokenKey(token) {
13
+ return token.slice(token.indexOf(':') + 1);
14
+ }
15
+ // Per source file, the set of component identity tokens ('kind:key') it exported the last time
16
+ // this ran. Lets a later edit to the same file detect "this used to export a component that's
17
+ // still live, and doesn't anymore" (a rename or delete) - see tungsten/docs/hmr.md's "orphaned
18
+ // components" note. Cleared naturally on a real page load, since this module state doesn't
19
+ // survive a full reload.
20
+ const previousFileExportIdentities = new Map();
21
+ // Given the freshly re-imported exports of one recompiled file, find every live component
22
+ // instance that came from a same-named, same-kind definition and rebuild it in place. See
23
+ // tungsten/docs/hmr.md for the full design and the reasoning behind the identity key.
24
+ export async function applyHmrModule(moduleExports, file) {
25
+ const instance = getCurrentInstance();
26
+ if (instance === undefined) return {
27
+ matched: false,
28
+ orphaned: false
29
+ };
30
+ let matchedCount = 0;
31
+ const currentIdentities = new Set();
32
+ for (const exportName in moduleExports) {
33
+ const exported = moduleExports[exportName];
34
+ if (typeof exported !== 'function') continue;
35
+ const NewType = exported; // eslint-disable-line no-type-assertion/no-type-assertion -- narrowed by typeof above, definitively a function/class value
36
+ const newKind = componentTypeKind(NewType);
37
+ const newKey = componentTypeIdentityKey(NewType);
38
+ currentIdentities.add(identityToken(newKind, newKey));
39
+ // snapshot: hot-swapping unregisters the old instance and registers its replacement,
40
+ // mutating registeredComponents mid-loop otherwise
41
+ for (const component of [...instance.registeredComponents]) {
42
+ const anyComponent = component; // eslint-disable-line no-type-assertion/no-type-assertion -- every registered component is actually a class instance or FunctionElement stand-in
43
+ if (liveComponentKind(anyComponent) !== newKind) continue;
44
+ if (liveComponentIdentityKey(anyComponent) !== newKey) continue;
45
+ const swapped = AnyComponentIsFunctionComponentStandIn(anyComponent) ? await hotSwapFunctionComponent(anyComponent, NewType) // eslint-disable-line no-type-assertion/no-type-assertion -- newKind === 'function' guaranteed by the kind check above
46
+ : await hotSwapClassComponent(anyComponent, NewType); // eslint-disable-line no-type-assertion/no-type-assertion -- newKind === 'class' guaranteed by the kind check above
47
+ if (swapped !== null) matchedCount++;
48
+ }
49
+ }
50
+ let orphaned = false;
51
+ if (file !== undefined) {
52
+ const previousIdentities = previousFileExportIdentities.get(file);
53
+ if (previousIdentities !== undefined) {
54
+ for (const previousToken of previousIdentities) {
55
+ if (currentIdentities.has(previousToken)) continue;
56
+ const kind = tokenKind(previousToken);
57
+ const key = tokenKey(previousToken);
58
+ const stillLive = [...instance.registeredComponents].some(component => {
59
+ const anyComponent = component; // eslint-disable-line no-type-assertion/no-type-assertion -- every registered component is actually a class instance or FunctionElement stand-in
60
+ return liveComponentKind(anyComponent) === kind && liveComponentIdentityKey(anyComponent) === key;
61
+ });
62
+ if (stillLive) {
63
+ orphaned = true;
64
+ break;
65
+ }
66
+ }
67
+ }
68
+ previousFileExportIdentities.set(file, currentIdentities);
69
+ }
70
+ return matchedCount > 0 ? {
71
+ matched: true,
72
+ count: matchedCount,
73
+ orphaned
74
+ } : {
75
+ matched: false,
76
+ orphaned
77
+ };
78
+ }
@@ -0,0 +1,9 @@
1
+ import type { AnyComponent } from '../AnyComponent.js';
2
+ import type { AnyComponentType } from '../AnyComponentType.js';
3
+ export type ComponentKind = 'class' | 'function';
4
+ export declare function componentTypeIdentityKey(Type: AnyComponentType): string;
5
+ export declare function componentTypeKind(Type: AnyComponentType): ComponentKind;
6
+ export declare function liveComponentType(component: AnyComponent): AnyComponentType;
7
+ export declare function liveComponentKind(component: AnyComponent): ComponentKind;
8
+ export declare function liveComponentIdentityKey(component: AnyComponent): string;
9
+ //# sourceMappingURL=componentIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentIdentity.d.ts","sourceRoot":"","sources":["../../src/hmr/componentIdentity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAO9D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,CAAA;AAEhD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAEvE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,aAAa,CAEvE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,gBAAgB,CAI3E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,aAAa,CAExE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAExE"}
@@ -0,0 +1,17 @@
1
+ import { AnyComponentIsFunctionComponentStandIn } from "../AnyComponent.js";
2
+ import { AnyComponentTypeIsClassComponentType } from "../AnyComponentType.js";
3
+ export function componentTypeIdentityKey(Type) {
4
+ return Type.tagName || Type.name || Type.displayName || '--unnamed--';
5
+ }
6
+ export function componentTypeKind(Type) {
7
+ return AnyComponentTypeIsClassComponentType(Type) ? 'class' : 'function';
8
+ }
9
+ export function liveComponentType(component) {
10
+ return AnyComponentIsFunctionComponentStandIn(component) ? component.func : component.constructor; // eslint-disable-line no-type-assertion/no-type-assertion -- constructor of a TungstenBaseComponent instance is its component type
11
+ }
12
+ export function liveComponentKind(component) {
13
+ return AnyComponentIsFunctionComponentStandIn(component) ? 'function' : 'class';
14
+ }
15
+ export function liveComponentIdentityKey(component) {
16
+ return componentTypeIdentityKey(liveComponentType(component));
17
+ }
@@ -0,0 +1,4 @@
1
+ import type { Instance } from '../Instance/Instance.js';
2
+ export declare function setCurrentInstance(instance: Instance): void;
3
+ export declare function getCurrentInstance(): Instance | undefined;
4
+ //# sourceMappingURL=instanceRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instanceRegistry.d.ts","sourceRoot":"","sources":["../../src/hmr/instanceRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAiBvD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAE3D;AAED,wBAAgB,kBAAkB,IAAI,QAAQ,GAAG,SAAS,CAEzD"}
@@ -0,0 +1,6 @@
1
+ export function setCurrentInstance(instance) {
2
+ globalThis.__tungstenHmrInstance = instance; // eslint-disable-line no-type-assertion/no-type-assertion -- narrowing globalThis to add one optional dev-only field
3
+ }
4
+ export function getCurrentInstance() {
5
+ return globalThis.__tungstenHmrInstance; // eslint-disable-line no-type-assertion/no-type-assertion -- narrowing globalThis to add one optional dev-only field
6
+ }
@@ -0,0 +1,10 @@
1
+ export type ReloadEventKind = 'js' | 'css';
2
+ export type ReloadEventInfo = {
3
+ kind: ReloadEventKind;
4
+ file?: string;
5
+ };
6
+ type ReloadListener = (info: ReloadEventInfo) => void;
7
+ export declare function onReloadEvent(listener: ReloadListener): () => void;
8
+ export declare function emitReloadEvent(kind: ReloadEventKind, file?: string): void;
9
+ export {};
10
+ //# sourceMappingURL=liveReloadHub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveReloadHub.d.ts","sourceRoot":"","sources":["../../src/hmr/liveReloadHub.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,KAAK,CAAA;AAE1C,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,eAAe,CAAA;IAGrB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,cAAc,GAAG,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;AAIrD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAGlE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAG1E"}
@@ -7,6 +7,12 @@ export function onReloadEvent(listener) {
7
7
  listeners.add(listener);
8
8
  return () => listeners.delete(listener);
9
9
  }
10
- export function emitReloadEvent(kind) {
11
- for (const listener of listeners) listener(kind);
10
+ export function emitReloadEvent(kind, file) {
11
+ const info = file !== undefined ? {
12
+ kind,
13
+ file
14
+ } : {
15
+ kind
16
+ };
17
+ for (const listener of listeners) listener(info);
12
18
  }
@@ -0,0 +1,2 @@
1
+ export declare function refreshStylesheets(doc?: Document): Promise<void>[];
2
+ //# sourceMappingURL=refreshStylesheets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshStylesheets.d.ts","sourceRoot":"","sources":["../../src/hmr/refreshStylesheets.ts"],"names":[],"mappings":"AAMA,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,QAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAY5E"}
@@ -0,0 +1,26 @@
1
+ // dev-only: cache-bust every stylesheet link on a CSS (or style-affecting JS) change, without a
2
+ // gap where no stylesheet is applied. Setting an existing <link>'s href directly can produce a
3
+ // visible flash - the load timing isn't guaranteed the same way across browsers - so instead a
4
+ // new <link> is inserted right after the old one and only removed once the new one has finished
5
+ // loading (or errored, so a failed fetch doesn't leave two stylesheets applied forever). There's
6
+ // a brief window where both are applied at once; that's harmless for a same-file edit.
7
+ export function refreshStylesheets(doc = document) {
8
+ const oldLinks = [...doc.querySelectorAll('link[rel="stylesheet"]')];
9
+ return oldLinks.map(oldLink => new Promise(resolve => {
10
+ const url = oldLink.getAttribute('href')?.split('?')[0] ?? '';
11
+ const newLink = doc.createElement('link');
12
+ newLink.rel = 'stylesheet';
13
+ newLink.href = `${url}?t=${Date.now()}`;
14
+ const finish = () => {
15
+ oldLink.remove();
16
+ resolve();
17
+ };
18
+ newLink.addEventListener('load', finish, {
19
+ once: true
20
+ });
21
+ newLink.addEventListener('error', finish, {
22
+ once: true
23
+ });
24
+ oldLink.insertAdjacentElement('afterend', newLink);
25
+ }));
26
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './useCallback.js';
2
+ export * from './useInstance.js';
2
3
  export * from './useMemo.js';
3
4
  export * from './useRef.js';
4
5
  export * from './useState.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
@@ -1,4 +1,5 @@
1
1
  export * from "./useCallback.js";
2
+ export * from "./useInstance.js";
2
3
  export * from "./useMemo.js";
3
4
  export * from "./useRef.js";
4
5
  export * from "./useState.js";
@@ -0,0 +1,3 @@
1
+ import type { Instance } from '../Instance/Instance.js';
2
+ export declare function useInstance(): Instance;
3
+ //# sourceMappingURL=useInstance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInstance.d.ts","sourceRoot":"","sources":["../../src/hooks/useInstance.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,wBAAgB,WAAW,IAAI,QAAQ,CAEtC"}
@@ -0,0 +1,4 @@
1
+ import { getCurrentComponent } from "./getCurrentComponent.js";
2
+ export function useInstance() {
3
+ return getCurrentComponent().__instance;
4
+ }
@@ -1,5 +1,15 @@
1
1
  import type { InstanceConfig } from '../Instance/InstanceConfig.js';
2
2
  import type { AppRoutes } from '../routing/AppRoutes.js';
3
+ import { DomPointer } from '../DomPointer.js';
3
4
  import { TungstenBaseComponentType } from '../Components.jsx';
5
+ import { Instance } from '../Instance/Instance.js';
6
+ import { type TaggedAttributeMismatch } from './renderHydrationMismatchBanner.js';
7
+ import '../hmr/applyHmrModule.js';
8
+ export type HydrateMeta = {
9
+ insideForm: boolean;
10
+ mismatches: TaggedAttributeMismatch[];
11
+ };
4
12
  export declare function hydrate(appRoutes: AppRoutes, RootComponent: TungstenBaseComponentType | null, instanceConfig: InstanceConfig): Promise<void>;
13
+ export declare function hydrateRootComponent<ComponentType extends TungstenBaseComponentType<any, any>>(instance: Instance, RootComponent: ComponentType, domPointer: DomPointer, meta: HydrateMeta, props?: InstanceType<ComponentType>['props'], // eslint-disable-line no-type-assertion/no-type-assertion -- default only reached when Props is empty, same as the hardcoded {} this replaces
14
+ routeParams?: Record<string, string>, routeData?: unknown): Promise<InstanceType<ComponentType>>;
5
15
  //# sourceMappingURL=hydrate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../../src/hydrate/hydrate.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAQnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AA0BxD,OAAO,EAAE,yBAAyB,EAAoD,MAAM,mBAAmB,CAAA;AAoC/G,wBAAsB,OAAO,CACzB,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,yBAAyB,GAAG,IAAI,EAC/C,cAAc,EAAE,cAAc,iBAyDjC"}
1
+ {"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../../src/hydrate/hydrate.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAQnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAoBxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAM7C,OAAO,EAAE,yBAAyB,EAAoD,MAAM,mBAAmB,CAAA;AAE/G,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAmBlD,OAAO,EAC4B,KAAK,uBAAuB,EAC9D,MAAM,oCAAoC,CAAA;AAQ3C,OAAO,0BAA0B,CAAA;AASjC,MAAM,MAAM,WAAW,GAAG;IACtB,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,uBAAuB,EAAE,CAAA;CACxC,CAAA;AAKD,wBAAsB,OAAO,CACzB,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,yBAAyB,GAAG,IAAI,EAC/C,cAAc,EAAE,cAAc,iBA2DjC;AAyBD,wBAAsB,oBAAoB,CACtC,aAAa,SAAS,yBAAyB,CAAC,GAAG,EAAE,GAAG,CAAC,EAEzD,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,WAAW,EAIjB,KAAK,GAAE,YAAY,CAAC,aAAa,CAAC,CAAC,OAAO,CAA8C,EAAE,8IAA8I;AACxO,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,SAAS,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CA6DtC"}
@@ -1,4 +1,4 @@
1
- import { integrateElementUpdateVdom } from "../update/integrateUpdateVdom.js";
1
+ import { applyUpdate, integrateElementUpdateVdom } from "../update/integrateUpdateVdom.js";
2
2
  //import type { RouteType } from '../routing/RouteType.js'
3
3
  import { $number, $string, makeRenderedContentNodeNonRendered, makeRenderedContentNodeClassComponent, makeRenderedContentNodeFunctionComponent } from "../RenderedContentNode.js";
4
4
  import { ContentNodeElementIsHtml, ContentNodeIsHtml, ContentNodeIsComponent, ContentNodeComponentIsClassComponent, ContentNodeIsElement } from "../ContentNode.js";
@@ -7,7 +7,7 @@ import { DomPointer } from "../DomPointer.js";
7
7
  import { DomRegion } from "../DomRegion.js";
8
8
  //import { FunctionComponent } from '../FunctionComponent.js'
9
9
  import { FunctionElement } from "../FunctionComponentStandIn.js";
10
- import { getContentFromFunctionComponent } from "../getContentFromFunctionComponent.js";
10
+ import { getStyledContentFromFunctionComponent } from "../getStyledContentFromFunctionComponent.js";
11
11
  import { StringIsHtmlEvent, htmlEvents } from "../htmlEvents.js";
12
12
  import { TungstenStatefulComponent } from "../Components.js";
13
13
  import { TungstenError } from "../TungstenError.js";
@@ -29,14 +29,24 @@ import { MatchedRoute } from "../routing/MatchedRoute.js";
29
29
  import { isDev } from "../isDev.js";
30
30
  import { warn } from "../appOutput.js";
31
31
  import { reconcileHydratedAttributes } from "./reconcileHydratedAttributes.js";
32
+ import { renderHydrationMismatchBanner } from "./renderHydrationMismatchBanner.js";
33
+ import { setCurrentInstance } from "../hmr/instanceRegistry.js";
34
+ // side-effect only: pulls applyHmrModule.js (and its clean, non-dynamic-import dependencies)
35
+ // into the framework's traced dependency graph so it gets copied to .packages/ and is servable
36
+ // to the browser. It is invoked from a raw, untraced inline script (processHead.ts) instead of
37
+ // a real import here, because it does a computed-URL dynamic import() to fetch whichever file
38
+ // just recompiled - and any dynamic import() with a non-literal argument anywhere in the traced
39
+ // graph makes the framework's package-copying step throw. See tungsten/docs/hmr.md.
40
+ import "../hmr/applyHmrModule.js";
32
41
  import { jsx as _jsx } from "tungsten/jsxRuntime.js";
33
42
  function debug(...texts) {
34
- console.log(...texts);
43
+ //console.log(...texts)
35
44
  //console.log(getStackTrace().split('\n')[2])
36
45
  }
37
46
  function makeDefaultHydrateMeta() {
38
47
  return {
39
- insideForm: false
48
+ insideForm: false,
49
+ mismatches: []
40
50
  };
41
51
  } // can we opto this out in production?
42
52
  export async function hydrate(appRoutes, RootComponent, instanceConfig) {
@@ -56,6 +66,7 @@ export async function hydrate(appRoutes, RootComponent, instanceConfig) {
56
66
  // const stores: TrueStore<any>[] = createStores(null, matchedRouteInfo, globalData)
57
67
  //console.log('hydration instance config', instanceConfig)
58
68
  const instance = new Instance(location, instanceConfig, null, appRoutes, routes, internalStore, stores, storeSubscriptions, globalData, matchedRouteInfo);
69
+ if (isDev) setCurrentInstance(instance);
59
70
  //const routes = instance.getRoutes()
60
71
  // we know which route was matched
61
72
  // if (typeof __tungsten_router_data__ !== 'undefined') {
@@ -80,6 +91,7 @@ export async function hydrate(appRoutes, RootComponent, instanceConfig) {
80
91
  // hydrateNode(content, null, domPointer, instance, meta)
81
92
  }
82
93
  instance.hydrationComplete = true;
94
+ if (isDev) renderHydrationMismatchBanner(meta.mismatches);
83
95
  //// Can components update while hydrating is still taking place
84
96
  //// -- probably yes
85
97
  //// Can we pause any further update until hydration completes, to retain coherency?
@@ -105,12 +117,20 @@ routes) {
105
117
  };
106
118
  }
107
119
  }
108
- async function hydrateRootComponent(instance, RootComponent, domPointer, meta) {
120
+ export async function hydrateRootComponent(instance, RootComponent, domPointer, meta,
121
+ // Real app hydration (hydrate(), above) always hydrates a root with no props of its own -
122
+ // route data comes through the store instead - so the default reproduces that. A test
123
+ // harness hydrating an arbitrary component (see testing/hydrateTestApp.ts) passes its own.
124
+ props = {},
125
+ // eslint-disable-line no-type-assertion/no-type-assertion -- default only reached when Props is empty, same as the hardcoded {} this replaces
126
+ routeParams, routeData) {
109
127
  debug('hydrateRootComponent');
128
+ // matches createTungstenRootComponent's identical cast, the create-path equivalent of this function
129
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
110
130
  const element = new RootComponent({
111
- props: {},
112
- routeParams: undefined,
113
- routeData: undefined,
131
+ props,
132
+ routeParams,
133
+ routeData,
114
134
  instance,
115
135
  parentElement: null
116
136
  });
@@ -146,6 +166,7 @@ async function hydrateRootComponent(instance, RootComponent, domPointer, meta) {
146
166
  // closingComment
147
167
  // )
148
168
  element.__didHydrate();
169
+ return element;
149
170
  }
150
171
  // if the root comp has a title, save it as the default title to use after navigation in the instance
151
172
  function handleRootTitle(rootElement) {
@@ -226,7 +247,12 @@ async function hydrateClassComponent(node, parentElement, domPointer, instance,
226
247
  const updateResult = await integrateElementUpdateVdom(element, initialContent);
227
248
  element.__currentContent = updateResult.renderedContent;
228
249
  element.__didHydrate();
229
- return makeRenderedContentNodeClassComponent(node, element, openingComment, closingComment);
250
+ const wrapper = makeRenderedContentNodeClassComponent(node, element, openingComment, closingComment);
251
+ // the reconciler's own equivalents (integrateUpdateVdom.ts) set this back-reference so
252
+ // HMR can locate/replace a live component's wrapper node - hydration builds its own
253
+ // wrapper independently and has to set it too. See tungsten/docs/hmr.md.
254
+ element.__renderedNode = wrapper;
255
+ return wrapper;
230
256
  } else {
231
257
  const renderedContent = await hydrateNode(initialContent, element, domPointer, instance, meta);
232
258
  const closingNode = domPointer.get();
@@ -243,7 +269,12 @@ async function hydrateClassComponent(node, parentElement, domPointer, instance,
243
269
  //console.log('hydrated', element.constructor.name, 'with content', renderedContent)
244
270
  element.__currentContent = renderedContent;
245
271
  element.__didHydrate();
246
- return makeRenderedContentNodeClassComponent(node, element, openingComment, closingComment);
272
+ const wrapper = makeRenderedContentNodeClassComponent(node, element, openingComment, closingComment);
273
+ // the reconciler's own equivalents (integrateUpdateVdom.ts) set this back-reference so
274
+ // HMR can locate/replace a live component's wrapper node - hydration builds its own
275
+ // wrapper independently and has to set it too. See tungsten/docs/hmr.md.
276
+ element.__renderedNode = wrapper;
277
+ return wrapper;
247
278
  }
248
279
  }
249
280
  async function renderClassComponent({
@@ -306,8 +337,7 @@ async function hydrateFunctionComponent(node, parentElement, domPointer, instanc
306
337
  //// InstantiateFunctionComponent???
307
338
  const functionComponentStandIn = new FunctionElement(Component, props, routeParams, routeData, instance, parentElement);
308
339
  setCurrentComponent(functionComponentStandIn);
309
- const content = await getContentFromFunctionComponent(functionComponentStandIn);
310
- //const content = await getContentFromFunctionComponent(Component, props)
340
+ const content = await getStyledContentFromFunctionComponent(functionComponentStandIn);
311
341
  clearCurrentComponent();
312
342
  //// Add to parent childNodes?
313
343
  const domIndexStart = domPointer.index;
@@ -328,7 +358,12 @@ async function hydrateFunctionComponent(node, parentElement, domPointer, instanc
328
358
  functionComponentStandIn.__domRegion = new DomRegion(domPointer.parent, domIndexStart, domIndexCount);
329
359
  functionComponentStandIn.__currentContent = renderedTree;
330
360
  //return functionComponentStandIn
331
- return makeRenderedContentNodeFunctionComponent(node, functionComponentStandIn, openingComment, closingComment);
361
+ const wrapper = makeRenderedContentNodeFunctionComponent(node, functionComponentStandIn, openingComment, closingComment);
362
+ // the reconciler's own equivalents (integrateUpdateVdom.ts) set this back-reference so HMR
363
+ // can locate/replace a live component's wrapper node - hydration builds its own wrapper
364
+ // independently and has to set it too. See tungsten/docs/hmr.md.
365
+ functionComponentStandIn.__renderedNode = wrapper;
366
+ return wrapper;
332
367
  }
333
368
  //// why don't we have html, nodes in here?
334
369
  async function hydrateNode(node, parentElement, domPointer, instance, meta) {
@@ -465,7 +500,7 @@ async function hydrateNodeSingle(node, parentElement, domPointer, instance, meta
465
500
  // node[$props].ref.current = domNode
466
501
  // }
467
502
  debug('hydarating atts');
468
- hydrateAttributes(node, domNode);
503
+ hydrateAttributes(node, domNode, meta);
469
504
  //!!! node.domElement = domNode
470
505
  const props = node[$props];
471
506
  if (node[$type] === 'textarea') {
@@ -501,7 +536,22 @@ async function hydrateNodeSingle(node, parentElement, domPointer, instance, meta
501
536
  debug('valid children', validChildren(node[$props].children), node[$props].children);
502
537
  const children = node[$props].children;
503
538
  let renderedChildren = $contentNull;
504
- if (node[$props].__opaque !== true && validChildren(children)) {
539
+ if (node[$type] === 'body' && instance.config.csr) {
540
+ // CSR: body shipped empty on purpose, nothing to hydrate against - create fresh.
541
+ if (parentElement === null) {
542
+ throwError('hydrateNodeSingle', 'CSR hydration reached <body> with no owning component');
543
+ }
544
+ const childDomPointer = new DomPointer(domNode);
545
+ renderedChildren = await applyUpdate({
546
+ tungstenElement: parentElement,
547
+ instance,
548
+ newNode: children,
549
+ oldNode: $contentNull,
550
+ domRegion: null,
551
+ domPointer: childDomPointer,
552
+ parentNode: null
553
+ });
554
+ } else if (node[$props].__opaque !== true && validChildren(children)) {
505
555
  debug('node.props.children', children);
506
556
  const childDomPointer = new DomPointer(domNode);
507
557
  renderedChildren = await hydrateNode(children, parentElement, childDomPointer, instance, meta);
@@ -546,17 +596,27 @@ async function hydrateNodeComponent(node, parentElement, domPointer, instance, m
546
596
  }
547
597
  // export type HTMLBindableElement = HTMLButtonElement | HTMLDataElement | HTMLInputElement | HTMLLIElement
548
598
  // | HTMLMeterElement | HTMLOptionElement | HTMLParamElement | HTMLProgressElement | HTMLSelectElement | HTMLTextAreaElement
549
- function hydrateAttributes(node, domNode) {
599
+ function hydrateAttributes(node, domNode, meta) {
550
600
  // handle bind attributes and merge together event handlers
551
601
  processAttributes(node);
552
602
  // Bring the server's attributes into line with what this render produced.
553
603
  // Runs in production as well as development: leaving a known-wrong value in
554
604
  // place is not better in production, it is only quieter. Only genuine
555
605
  // differences are written, so a page that matches costs reads and no
556
- // writes. The report is dev-only, because a mismatch is a bug in the
557
- // application's rendering rather than something a user can act on.
606
+ // writes. Collection always runs (it is what a hydration-test harness reads
607
+ // to assert on - see testing/hydrateTestApp.ts); only the console report and
608
+ // the on-page banner (hydrate(), below) are dev-only, because a mismatch is
609
+ // a bug in the application's rendering rather than something a user can act on.
558
610
  if (ContentNodeElementIsHtml(node)) {
559
- reconcileHydratedAttributes(node, domNode, isDev ? mismatch => warn(`hydration mismatch on <${node[$type]}>:` + ` ${mismatch.name} rendered as ${JSON.stringify(mismatch.expected)}` + ` but the server sent ${JSON.stringify(mismatch.actual)}.` + ` The rendered value has been applied.`) : undefined);
611
+ reconcileHydratedAttributes(node, domNode, mismatch => {
612
+ meta.mismatches.push({
613
+ tagName: node[$type],
614
+ ...mismatch
615
+ });
616
+ if (isDev) {
617
+ warn(`hydration mismatch on <${node[$type]}>:` + ` ${mismatch.name} rendered as ${JSON.stringify(mismatch.expected)}` + ` but the server sent ${JSON.stringify(mismatch.actual)}.` + ` The rendered value has been applied.`);
618
+ }
619
+ });
560
620
  }
561
621
  debug('--\nhydrateAttributes', domNode);
562
622
  for (const key in node[$props]) {
@@ -674,6 +734,8 @@ function hydrateAttributes(node, domNode) {
674
734
  function processAttributes(node) {
675
735
  const props = node[$props];
676
736
  debug('--\nprocessAttributes', node);
737
+ // set a button without specified type to button, so buttons don't submit forms unless instructed to
738
+ if (node[$type] === 'button' && !('type' in props)) props.type = 'button';
677
739
  for (const key in node[$props]) {
678
740
  if (key === 'bind' && ContentNodeElementIsHtml(node)) {
679
741
  const eventName = 'onInput';
@@ -1 +1 @@
1
- {"version":3,"file":"reconcileHydratedAttributes.d.ts","sourceRoot":"","sources":["../../src/hydrate/reconcileHydratedAttributes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAIxD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,gFAAgF;IAChF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AA6BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACvC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GACnD,IAAI,CAkCN"}
1
+ {"version":3,"file":"reconcileHydratedAttributes.d.ts","sourceRoot":"","sources":["../../src/hydrate/reconcileHydratedAttributes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAKxD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,gFAAgF;IAChF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AA6BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACvC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GACnD,IAAI,CAuCN"}
@@ -1,5 +1,6 @@
1
1
  import { $props } from "../contentNodeSymbols.js";
2
2
  import { processProps } from "../render/processProps.js";
3
+ import { booleanAttributeValue } from "../booleanAttributeValue.js";
3
4
  /**
4
5
  * The attribute value a render produces for a prop, or null for "no attribute".
5
6
  *
@@ -7,8 +8,8 @@ import { processProps } from "../render/processProps.js";
7
8
  * the server and `addAttributes()` on the client — so that a value which
8
9
  * round-trips unchanged compares equal here.
9
10
  */
10
- function attributeValue(value) {
11
- if (typeof value === 'boolean') return value ? '' : null;
11
+ function attributeValue(name, value) {
12
+ if (typeof value === 'boolean') return booleanAttributeValue(name, value);
12
13
  if (value === undefined || value === null) return null;
13
14
  return String(value);
14
15
  }
@@ -40,14 +41,22 @@ function setAttribute(domNode, name, value) {
40
41
  */
41
42
  export function reconcileHydratedAttributes(node, domNode, onMismatch) {
42
43
  // A copy: processProps() rewrites what it is given, and these props stay in
43
- // the content tree for the next update to diff against.
44
+ // the content tree for the next update to diff against. children is pulled out
45
+ // first, same as the server renderer (renderingTreeToHtml.ts) and the client
46
+ // update path (integrateUpdateVdom.ts's processAttributes()) both do - it is
47
+ // rendered content, not an HTML attribute, and processProps() was never meant
48
+ // to receive it.
49
+ const {
50
+ children: _children,
51
+ ...restProps
52
+ } = node[$props]; // eslint-disable-line @typescript-eslint/no-unused-vars
44
53
  const expected = processProps({
45
- ...node[$props]
54
+ ...restProps
46
55
  });
47
56
  const handled = new Set();
48
57
  for (const name in expected) {
49
58
  handled.add(name.toLowerCase());
50
- const value = attributeValue(expected[name]);
59
+ const value = attributeValue(name, expected[name]);
51
60
  const actual = domNode.getAttribute(name);
52
61
  if (value === actual) continue;
53
62
  if (value === null) removeAttribute(domNode, name);else setAttribute(domNode, name, value);
@@ -0,0 +1,7 @@
1
+ import type { AttributeMismatch } from './reconcileHydratedAttributes.js';
2
+ export type TaggedAttributeMismatch = AttributeMismatch & {
3
+ tagName: string;
4
+ };
5
+ export declare const hydrationMismatchAttribute = "data-tungsten-hydration-mismatches";
6
+ export declare function renderHydrationMismatchBanner(mismatches: readonly TaggedAttributeMismatch[], doc?: Document): void;
7
+ //# sourceMappingURL=renderHydrationMismatchBanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderHydrationMismatchBanner.d.ts","sourceRoot":"","sources":["../../src/hydrate/renderHydrationMismatchBanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AAEzE,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAI7E,eAAO,MAAM,0BAA0B,uCAAuC,CAAA;AA2C9E,wBAAgB,6BAA6B,CACzC,UAAU,EAAE,SAAS,uBAAuB,EAAE,EAC9C,GAAG,GAAE,QAAmB,GACzB,IAAI,CA4BN"}