cluaupp 1.5.0 → 1.5.2-cf

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 (386) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +11 -6
  3. package/api/CHANGELOG.md +3 -0
  4. package/api/chat.js +74 -0
  5. package/api/fixtures/roblox/README.md +6 -0
  6. package/api/fixtures/roblox/aux/sample.d.luau +6 -0
  7. package/api/fixtures/roblox/mini/Mini-API-Dump.json +72 -0
  8. package/api/generated/bench-latest.json +39 -0
  9. package/api/generated/capability-profile.json +76 -0
  10. package/api/generated/lsp-index.json +1 -0
  11. package/api/generated/luau/classes.d.luau +11221 -0
  12. package/api/generated/luau/datatypes.d.luau +327 -0
  13. package/api/generated/luau/enums.d.luau +4918 -0
  14. package/api/generated/luau/globals.d.luau +12 -0
  15. package/api/manifests/roblox-target.manifest.json +22 -0
  16. package/api/normalized/roblox-target.profile.json +237461 -0
  17. package/api/overrides/classes.json +8 -0
  18. package/api/overrides/compatibility.json +9 -0
  19. package/api/overrides/datatypes.json +1579 -0
  20. package/api/overrides/enums.json +8 -0
  21. package/api/overrides/globals.json +8 -0
  22. package/api/overrides/type-mappings.json +9 -0
  23. package/api/roblox-api.lock.json +9 -0
  24. package/bin/cluaupp.js +36 -0
  25. package/data/Mini-API-Dump.json +1 -0
  26. package/editors/vscode/README.md +12 -10
  27. package/editors/vscode/extension.js +82 -0
  28. package/editors/vscode/icons/axiom.svg +4 -0
  29. package/editors/vscode/icons/bloom.svg +5 -0
  30. package/editors/vscode/icons/helm.svg +4 -0
  31. package/editors/vscode/icons/hive.svg +5 -0
  32. package/editors/vscode/icons/mint.svg +4 -0
  33. package/editors/vscode/icons/shift.svg +6 -0
  34. package/editors/vscode/language-configuration-schema.json +24 -0
  35. package/editors/vscode/package.json +172 -12
  36. package/editors/vscode/snippets/axiom.json +12 -0
  37. package/editors/vscode/snippets/bloom.json +12 -0
  38. package/editors/vscode/snippets/helm.json +12 -0
  39. package/editors/vscode/snippets/hive.json +12 -0
  40. package/editors/vscode/snippets/mint.json +12 -0
  41. package/editors/vscode/snippets/shift.json +17 -0
  42. package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
  43. package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
  44. package/editors/vscode/syntaxes/clpp.tmLanguage.json +90 -0
  45. package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
  46. package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
  47. package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
  48. package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
  49. package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
  50. package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
  51. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
  52. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
  53. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
  54. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
  55. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
  56. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
  57. package/examples/game/.cluaupp/compile-cache/index.json +12 -0
  58. package/examples/game/.cluaupp/datamodel-profile.json +94 -0
  59. package/examples/game/.vscode/settings.json +12 -1
  60. package/examples/game/cluaupp.config.json +1 -1
  61. package/examples/game/default.project.json +13 -16
  62. package/examples/game/include/clpp/datatypes.clh +337 -373
  63. package/examples/game/include/clpp/generated/datamodel.clh +25 -0
  64. package/examples/game/include/clpp/generated/enums.clh +1 -1
  65. package/examples/game/include/clpp/generated/instances.clh +41135 -41064
  66. package/examples/game/include/clpp/libs/axiom.clh +1 -1
  67. package/examples/game/include/clpp/libs/math.clh +14 -0
  68. package/examples/game/include/clpp/libs/spring.clh +17 -0
  69. package/examples/game/include/clpp/libs/ward.clh +1 -0
  70. package/examples/game/include/clpp/roblox.clh +3 -4
  71. package/examples/game/libs/ArrayIndexer/init.luau +209 -0
  72. package/examples/game/libs/Axiom/init.luau +608 -0
  73. package/examples/game/libs/Bloom/init.luau +433 -0
  74. package/examples/game/libs/Coil/init.luau +215 -0
  75. package/examples/game/libs/Crest/init.luau +426 -0
  76. package/examples/game/libs/Echo/init.luau +417 -0
  77. package/examples/game/libs/Ember/init.luau +365 -0
  78. package/examples/game/libs/Flare/init.luau +717 -0
  79. package/examples/game/libs/Gleam/init.luau +729 -0
  80. package/examples/game/libs/Guide/init.luau +215 -0
  81. package/examples/game/libs/Helm/init.luau +377 -0
  82. package/examples/game/libs/Hive/init.luau +241 -0
  83. package/examples/game/libs/Keep/Client.luau +114 -0
  84. package/examples/game/libs/Keep/Data.luau +883 -0
  85. package/examples/game/libs/Keep/Engine.luau +211 -0
  86. package/examples/game/libs/Keep/Enum.luau +6 -0
  87. package/examples/game/libs/Keep/Enums.luau +10 -0
  88. package/examples/game/libs/Keep/Path.luau +236 -0
  89. package/examples/game/libs/Keep/Replicator.luau +298 -0
  90. package/examples/game/libs/Keep/Server.luau +251 -0
  91. package/examples/game/libs/Keep/Store.luau +652 -0
  92. package/examples/game/libs/Keep/Trade.luau +455 -0
  93. package/examples/game/libs/Keep/init.luau +205 -0
  94. package/examples/game/libs/Lens/init.luau +609 -0
  95. package/examples/game/libs/Mint/init.luau +279 -0
  96. package/examples/game/libs/Net/init.luau +156 -0
  97. package/examples/game/libs/Net/src/codec.luau +224 -0
  98. package/examples/game/libs/Occlude/init.luau +117 -0
  99. package/examples/game/libs/Pin/init.luau +309 -0
  100. package/examples/game/libs/Promise/LICENSE +21 -0
  101. package/examples/game/libs/Promise/_impl/LICENSE +21 -0
  102. package/examples/game/libs/Promise/_impl/init.lua +1991 -0
  103. package/examples/game/libs/Promise/init.lua +1990 -0
  104. package/examples/game/libs/Promise/init.luau +13 -0
  105. package/examples/game/libs/Promise/types.luau +46 -0
  106. package/examples/game/libs/Roster/init.luau +686 -0
  107. package/examples/game/libs/SOURCES.md +31 -0
  108. package/examples/game/libs/Shift/init.luau +238 -0
  109. package/examples/game/libs/Spark/init.luau +487 -0
  110. package/examples/game/libs/Stage/init.luau +178 -0
  111. package/examples/game/libs/Sweep/init.luau +259 -0
  112. package/examples/game/libs/Trace/init.luau +213 -0
  113. package/examples/game/libs/Ward/init.luau +211 -0
  114. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
  115. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
  116. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
  117. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
  118. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
  119. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
  120. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
  121. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
  122. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
  123. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
  124. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
  125. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
  126. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
  127. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
  128. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
  129. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
  130. package/examples/game/src/Client/Controllers/DataController.client.clpp +7 -0
  131. package/examples/game/src/Client/Main.client.clpp +4 -0
  132. package/examples/game/src/Modules/Core/Guard.server.clpp +7 -0
  133. package/examples/game/src/{ServerScriptService/Handlers → Modules/Core}/PlayerHandler.server.clpp +3 -3
  134. package/examples/game/src/{ServerScriptService → Server}/Boot/DataBoot.server.clpp +3 -3
  135. package/examples/game/src/Server/Main.server.clpp +4 -0
  136. package/examples/game/stylua.toml +9 -0
  137. package/generated/api/build-profile.js +115 -0
  138. package/generated/api/cache.js +44 -0
  139. package/generated/api/coverage.js +32 -0
  140. package/generated/api/diff.js +125 -0
  141. package/generated/api/generators/clpp-headers.js +353 -0
  142. package/generated/api/generators/docs-reference.js +7 -0
  143. package/generated/api/generators/lsp-index.js +81 -0
  144. package/generated/api/generators/luau-defs.js +94 -0
  145. package/generated/api/ide.js +76 -0
  146. package/generated/api/identifier.js +47 -0
  147. package/generated/api/index.js +324 -0
  148. package/generated/api/loader.js +57 -0
  149. package/generated/api/merge.js +88 -0
  150. package/generated/api/model.js +5 -0
  151. package/generated/api/normalize.js +231 -0
  152. package/generated/api/overrides-validate.js +58 -0
  153. package/generated/api/perf.js +12 -0
  154. package/generated/api/registry.js +136 -0
  155. package/generated/api/release.js +44 -0
  156. package/generated/api/resolver.js +250 -0
  157. package/generated/api/sources/aux-types-diff.js +75 -0
  158. package/generated/api/sources/client-tracker.js +11 -0
  159. package/generated/api/sources/creator-docs.js +42 -0
  160. package/generated/api/sources/luau-types.js +34 -0
  161. package/generated/api/sources/mini-dump.js +17 -0
  162. package/generated/api/sources/studio-api.js +8 -0
  163. package/generated/api/sources/studio-apiv2.js +11 -0
  164. package/generated/api/sources/studio-full-api.js +8 -0
  165. package/generated/api/studio-smoke.js +80 -0
  166. package/generated/api/type-parse.js +49 -0
  167. package/generated/api/understander.js +51 -0
  168. package/generated/api/validate.js +135 -0
  169. package/generated/api-cli.js +421 -0
  170. package/generated/cli.js +16 -5
  171. package/generated/clpp/contract.js +3 -3
  172. package/generated/clpp/format-luau.js +236 -0
  173. package/generated/clpp/index.js +13 -1
  174. package/generated/clpp/modules.js +232 -0
  175. package/generated/clpp/postprocess.js +86 -5
  176. package/generated/clpp/rewrite-janitor.js +145 -0
  177. package/generated/clpp/runner.js +14 -2
  178. package/generated/compile.js +82 -0
  179. package/generated/flare/parse.js +12 -1
  180. package/generated/intellisense.js +57 -1
  181. package/generated/native/index.js +217 -16
  182. package/generated/target/authority-check.js +136 -0
  183. package/generated/target/authority-graph.js +74 -0
  184. package/generated/target/build-cache.js +112 -0
  185. package/generated/target/capabilities.js +89 -0
  186. package/generated/target/capability-profile.js +30 -0
  187. package/generated/target/component-contracts.js +60 -0
  188. package/generated/target/context-check.js +160 -0
  189. package/generated/target/datamodel-check.js +170 -0
  190. package/generated/target/datamodel-generate.js +74 -0
  191. package/generated/target/datamodel.js +233 -0
  192. package/generated/target/diagnostics.js +63 -0
  193. package/generated/target/doctor.js +152 -0
  194. package/generated/target/flare-version.js +58 -0
  195. package/generated/target/gen-rojo-tree.js +118 -0
  196. package/generated/target/get-service.js +69 -0
  197. package/generated/target/lifetime-check.js +47 -0
  198. package/generated/target/luau-stamp.js +39 -0
  199. package/generated/target/optimizer-advise.js +88 -0
  200. package/generated/target/optimizer-apply.js +44 -0
  201. package/generated/target/optimizer-soa.js +254 -0
  202. package/generated/target/parallel-check.js +136 -0
  203. package/generated/target/pgo.js +148 -0
  204. package/generated/target/project-docs.js +69 -0
  205. package/generated/target/project-graph.js +71 -0
  206. package/generated/target/roblox.js +63 -0
  207. package/generated/target/security-check.js +41 -0
  208. package/generated/target/source-map.js +25 -0
  209. package/generated/target/studio-bridge.js +112 -0
  210. package/generated/utils/project.js +186 -8
  211. package/generated/utils/rojo-mapper.js +11 -3
  212. package/include/clpp/datatypes.clh +337 -373
  213. package/include/clpp/generated/enums.clh +1 -1
  214. package/include/clpp/generated/instances.clh +41135 -41064
  215. package/include/clpp/libs/axiom.clh +1 -1
  216. package/include/clpp/libs/hive.clh +1 -0
  217. package/include/clpp/libs/keep.clh +2 -0
  218. package/include/clpp/libs/math.clh +14 -0
  219. package/include/clpp/libs/spring.clh +17 -0
  220. package/include/clpp/libs/ward.clh +1 -0
  221. package/include/clpp/roblox.clh +3 -4
  222. package/{examples/game/src/ReplicatedFirst/Loading → native/bin}/.gitkeep +1 -1
  223. package/package.json +14 -3
  224. package/plugins/CluauppNav/Plugin.luau +207 -0
  225. package/plugins/CluauppNav/ProfileLogger.luau +27 -0
  226. package/plugins/CluauppNav/README.md +24 -0
  227. package/runtime/Axiom/init.luau +10 -7
  228. package/runtime/Coil/init.luau +8 -2
  229. package/runtime/Crest/init.luau +1 -0
  230. package/runtime/Flare/init.luau +2 -1
  231. package/runtime/Gleam/init.luau +15 -4
  232. package/runtime/Hive/init.luau +36 -14
  233. package/runtime/Pin/init.luau +5 -2
  234. package/runtime/Roster/init.luau +2 -0
  235. package/runtime/Spark/init.luau +3 -0
  236. package/runtime/Sweep/init.luau +2 -0
  237. package/runtime/Trace/init.luau +3 -0
  238. package/runtime/Ward/init.luau +38 -5
  239. package/rust/cluaupp/Cargo.lock +795 -0
  240. package/rust/cluaupp/Cargo.toml +17 -0
  241. package/rust/cluaupp/src/main.rs +717 -0
  242. package/scripts/postinstall-editor.js +17 -0
  243. package/scripts/postinstall-native.js +52 -0
  244. package/skills/README.md +13 -0
  245. package/skills/clpp-hive-flare/SKILL.md +79 -0
  246. package/skills/clpp-language/SKILL.md +123 -0
  247. package/skills/clpp-language/compiler.md +89 -0
  248. package/skills/clpp-style/SKILL.md +95 -0
  249. package/src/api/build-profile.ts +138 -0
  250. package/src/api/cache.ts +45 -0
  251. package/src/api/coverage.ts +46 -0
  252. package/src/api/diff.ts +143 -0
  253. package/src/api/generators/clpp-headers.ts +377 -0
  254. package/src/api/generators/docs-reference.ts +11 -0
  255. package/src/api/generators/lsp-index.ts +106 -0
  256. package/src/api/generators/luau-defs.ts +98 -0
  257. package/src/api/ide.ts +87 -0
  258. package/src/api/identifier.ts +47 -0
  259. package/src/api/index.ts +269 -0
  260. package/src/api/loader.ts +60 -0
  261. package/src/api/merge.ts +126 -0
  262. package/src/api/model.ts +283 -0
  263. package/src/api/normalize.ts +257 -0
  264. package/src/api/overrides-validate.ts +58 -0
  265. package/src/api/perf.ts +15 -0
  266. package/src/api/registry.ts +162 -0
  267. package/src/api/release.ts +47 -0
  268. package/src/api/resolver.ts +255 -0
  269. package/src/api/sources/aux-types-diff.ts +81 -0
  270. package/src/api/sources/client-tracker.ts +10 -0
  271. package/src/api/sources/creator-docs.ts +37 -0
  272. package/src/api/sources/luau-types.ts +30 -0
  273. package/src/api/sources/mini-dump.ts +50 -0
  274. package/src/api/sources/studio-api.ts +7 -0
  275. package/src/api/sources/studio-apiv2.ts +10 -0
  276. package/src/api/sources/studio-full-api.ts +7 -0
  277. package/src/api/studio-smoke.ts +82 -0
  278. package/src/api/type-parse.ts +48 -0
  279. package/src/api/understander.ts +72 -0
  280. package/src/api/validate.ts +160 -0
  281. package/src/api-cli.ts +493 -0
  282. package/src/api.generated.js +37 -22
  283. package/src/cli.ts +21 -6
  284. package/src/clpp/contract.ts +34 -3
  285. package/src/clpp/format-luau.ts +262 -0
  286. package/src/clpp/index.ts +13 -2
  287. package/src/clpp/modules.ts +257 -0
  288. package/src/clpp/postprocess.ts +100 -5
  289. package/src/clpp/rewrite-janitor.ts +156 -0
  290. package/src/clpp/runner.ts +14 -2
  291. package/src/compile.ts +87 -0
  292. package/src/flare/parse.ts +14 -1
  293. package/src/flare/types.ts +2 -0
  294. package/src/intellisense.ts +58 -1
  295. package/src/native/index.ts +225 -16
  296. package/src/target/authority-check.ts +162 -0
  297. package/src/target/authority-graph.ts +80 -0
  298. package/src/target/build-cache.ts +129 -0
  299. package/src/target/capabilities.ts +115 -0
  300. package/src/target/capability-profile.ts +25 -0
  301. package/src/target/component-contracts.ts +64 -0
  302. package/src/target/context-check.ts +177 -0
  303. package/src/target/datamodel-check.ts +188 -0
  304. package/src/target/datamodel-generate.ts +78 -0
  305. package/src/target/datamodel.ts +261 -0
  306. package/src/target/diagnostics.ts +67 -0
  307. package/src/target/doctor.ts +171 -0
  308. package/src/target/flare-version.ts +61 -0
  309. package/src/target/gen-rojo-tree.ts +123 -0
  310. package/src/target/get-service.ts +85 -0
  311. package/src/target/lifetime-check.ts +45 -0
  312. package/src/target/luau-stamp.ts +33 -0
  313. package/src/target/optimizer-advise.ts +93 -0
  314. package/src/target/optimizer-apply.ts +63 -0
  315. package/src/target/optimizer-soa.ts +270 -0
  316. package/src/target/parallel-check.ts +135 -0
  317. package/src/target/pgo.ts +157 -0
  318. package/src/target/project-docs.ts +68 -0
  319. package/src/target/project-graph.ts +75 -0
  320. package/src/target/roblox.ts +78 -0
  321. package/src/target/security-check.ts +40 -0
  322. package/src/target/source-map.ts +36 -0
  323. package/src/target/studio-bridge.ts +140 -0
  324. package/src/types.ts +14 -0
  325. package/src/utils/project.ts +192 -9
  326. package/src/utils/rojo-mapper.ts +12 -3
  327. package/stylua.toml +9 -0
  328. package/templates/game/.vscode/settings.json +7 -1
  329. package/templates/game/cluaupp.config.json +1 -1
  330. package/templates/game/default.project.json +13 -16
  331. package/templates/game/include/clpp/datatypes.clh +337 -373
  332. package/templates/game/include/clpp/generated/enums.clh +1 -1
  333. package/templates/game/include/clpp/generated/instances.clh +41135 -41064
  334. package/templates/game/include/clpp/libs/axiom.clh +1 -1
  335. package/templates/game/include/clpp/libs/ward.clh +1 -0
  336. package/templates/game/include/clpp/roblox.clh +3 -4
  337. package/templates/game/src/Client/Controllers/DataController.client.clpp +7 -0
  338. package/templates/game/src/Client/Main.client.clpp +4 -0
  339. package/templates/game/src/Modules/Core/Guard.server.clpp +7 -0
  340. package/templates/game/src/{ServerScriptService/Handlers → Modules/Core}/PlayerHandler.server.clpp +3 -3
  341. package/templates/game/src/{ServerScriptService → Server}/Boot/DataBoot.server.clpp +3 -3
  342. package/templates/game/src/Server/Main.server.clpp +4 -0
  343. package/templates/game/stylua.toml +9 -0
  344. package/examples/game/src/ReplicatedStorage/Shared/Constants/Classes/.gitkeep +0 -1
  345. package/examples/game/src/ReplicatedStorage/Shared/Constants/Primitives/.gitkeep +0 -1
  346. package/examples/game/src/ReplicatedStorage/Shared/Modules/.gitkeep +0 -1
  347. package/examples/game/src/ReplicatedStorage/Shared/Net/.gitkeep +0 -1
  348. package/examples/game/src/ReplicatedStorage/Shared/Services/.gitkeep +0 -1
  349. package/examples/game/src/ReplicatedStorage/Shared/Types/.gitkeep +0 -1
  350. package/examples/game/src/ReplicatedStorage/Shared/Utils/.gitkeep +0 -1
  351. package/examples/game/src/ServerScriptService/Components/.gitkeep +0 -1
  352. package/examples/game/src/ServerScriptService/Configuration/ServerConfig.clp +0 -4
  353. package/examples/game/src/ServerScriptService/Handlers/Guard.server.clpp +0 -7
  354. package/examples/game/src/ServerScriptService/Services/.gitkeep +0 -1
  355. package/examples/game/src/ServerStorage/Configuration/.gitkeep +0 -1
  356. package/examples/game/src/ServerStorage/Modules/.gitkeep +0 -1
  357. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.clpp +0 -6
  358. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Combat/.gitkeep +0 -1
  359. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Movement/.gitkeep +0 -1
  360. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.clpp +0 -7
  361. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Input/.gitkeep +0 -1
  362. package/examples/game/src/StarterPlayer/StarterPlayerScripts/UI/.gitkeep +0 -1
  363. package/templates/game/src/ReplicatedFirst/Loading/.gitkeep +0 -1
  364. package/templates/game/src/ReplicatedStorage/Shared/Constants/Classes/.gitkeep +0 -1
  365. package/templates/game/src/ReplicatedStorage/Shared/Constants/Primitives/.gitkeep +0 -1
  366. package/templates/game/src/ReplicatedStorage/Shared/Modules/.gitkeep +0 -1
  367. package/templates/game/src/ReplicatedStorage/Shared/Net/.gitkeep +0 -1
  368. package/templates/game/src/ReplicatedStorage/Shared/Services/.gitkeep +0 -1
  369. package/templates/game/src/ReplicatedStorage/Shared/Types/.gitkeep +0 -1
  370. package/templates/game/src/ReplicatedStorage/Shared/Utils/.gitkeep +0 -1
  371. package/templates/game/src/ServerScriptService/Components/.gitkeep +0 -1
  372. package/templates/game/src/ServerScriptService/Configuration/ServerConfig.clp +0 -4
  373. package/templates/game/src/ServerScriptService/Handlers/Guard.server.clpp +0 -7
  374. package/templates/game/src/ServerScriptService/Services/.gitkeep +0 -1
  375. package/templates/game/src/ServerStorage/Configuration/.gitkeep +0 -1
  376. package/templates/game/src/ServerStorage/Modules/.gitkeep +0 -1
  377. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.clpp +0 -6
  378. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Combat/.gitkeep +0 -1
  379. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Movement/.gitkeep +0 -1
  380. package/templates/game/src/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.clpp +0 -7
  381. package/templates/game/src/StarterPlayer/StarterPlayerScripts/Input/.gitkeep +0 -1
  382. package/templates/game/src/StarterPlayer/StarterPlayerScripts/UI/.gitkeep +0 -1
  383. /package/examples/game/src/{ReplicatedStorage/Shared/Net → Declarations}/Net.flare +0 -0
  384. /package/examples/game/src/{ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh → Include/GameTypes.clh} +0 -0
  385. /package/templates/game/src/{ReplicatedStorage/Shared/Net → Declarations}/Net.flare +0 -0
  386. /package/templates/game/src/{ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh → Include/GameTypes.clh} +0 -0
@@ -1,6 +1,16 @@
1
1
  import { insertPreamble, libraryNamesFromIncludes, MODULES, requireCluauppLib } from "../libs.js";
2
2
  import type { CompileArtifact } from "./contract.js";
3
+ import { formatLuauRoblox } from "./format-luau.js";
4
+ import {
5
+ applyNativeHintsToLuau,
6
+ ensureGameServices,
7
+ rewriteGameRootedRequires,
8
+ } from "./modules.js";
9
+ import { rewriteGetServiceLuau } from "../target/get-service.js";
3
10
  import { isTaggedScript } from "./paths.js";
11
+ import { rewriteSweepJanitor } from "./rewrite-janitor.js";
12
+
13
+ export { formatLuauRoblox } from "./format-luau.js";
4
14
 
5
15
  export type PostprocessOptions = {
6
16
  relativeName: string;
@@ -10,6 +20,8 @@ export type PostprocessOptions = {
10
20
  strict?: boolean;
11
21
  skipInit?: boolean;
12
22
  source?: string;
23
+ nativeHints?: string[];
24
+ layoutHints?: string[];
13
25
  };
14
26
 
15
27
  function insertAfterHeader(luau: string, block: string): string {
@@ -62,14 +74,96 @@ function rewriteClppLibs(luau: string, relativeName?: string): string {
62
74
  return next;
63
75
  }
64
76
 
65
- function ensureReplicatedStorage(luau: string): string {
66
- if (!luau.includes("CluauppLibs")) {
77
+ function rewriteReplicatedStorageRequires(luau: string): string {
78
+ let next = rewriteGameRootedRequires(luau);
79
+ next = ensureGameServices(next);
80
+ return next;
81
+ }
82
+
83
+ function rewriteRosterNew(luau: string): string {
84
+ return String(luau)
85
+ .replace(/Instance\.new\(\s*["']Roster["']\s*\)/g, "Roster.new()")
86
+ .replace(/Instance\.new\(\s*["']Roster["']\s*,/g, "Roster.new(")
87
+ .replace(/\bRoster\.New\s*\(/g, "Roster.new(")
88
+ .replace(/\bSweep\.New\s*\(/g, "Sweep.new(")
89
+ .replace(/\bSpark\.New\s*\(/g, "Spark.new(")
90
+ .replace(/\bCoil\.New\s*\(/g, "Coil.new(")
91
+ .replace(/\bPin\.new_\s*\(/g, "Pin.new(")
92
+ .replace(/\bCrest\.new_\s*\(/g, "Crest.new(")
93
+ .replace(/\bStage\.new_\s*\(/g, "Stage.new(");
94
+ }
95
+
96
+ function rewriteCamelColon(luau: string): string {
97
+ // CL++ emits instance calls as `.Method(` without self. Any camelCase receiver +
98
+ // PascalCase call needs `:`. Static calls stay on PascalCase modules (Roster.New, Trace.Display).
99
+ let next = String(luau).replace(
100
+ /\b([a-z][A-Za-z0-9]*)(?<!:)\.([A-Z][A-Za-z0-9]*)\s*\(/g,
101
+ "$1:$2(",
102
+ );
103
+ const lowerMethods = ["setName", "setLabel", "getStatus", "display", "andThen", "catch_", "finally"];
104
+ for (const name of lowerMethods) {
105
+ next = next.replace(new RegExp(`\\b([a-z][A-Za-z0-9]*)(?<!:)\\.${name}\\s*\\(`, "g"), `$1:${name}(`);
106
+ }
107
+ return next;
108
+ }
109
+
110
+ function rewriteHiveWorldType(luau: string): string {
111
+ if (!/\bHiveWorld\b/.test(luau)) {
67
112
  return luau;
68
113
  }
69
- if (/GetService\(\s*"ReplicatedStorage"\s*\)/.test(luau)) {
114
+ let next = String(luau).replace(/(?<![\w.])HiveWorld\b/g, "Hive.HiveWorld");
115
+ const hasHive = /CluauppLibs\.Hive\b/.test(next) || /\b(?:const|local)\s+Hive\b/.test(next);
116
+ if (!hasHive) {
117
+ next = next.replace(/\bHive\.HiveWorld\b/g, "any");
118
+ }
119
+ return next;
120
+ }
121
+
122
+ function rewriteCFrameColon(luau: string): string {
123
+ const methods = [
124
+ "ToWorldSpace",
125
+ "ToObjectSpace",
126
+ "PointToWorldSpace",
127
+ "PointToObjectSpace",
128
+ "VectorToWorldSpace",
129
+ "VectorToObjectSpace",
130
+ "IsStudio",
131
+ "IsClient",
132
+ "IsServer",
133
+ ];
134
+ let next = String(luau);
135
+ for (const name of methods) {
136
+ next = next.replace(new RegExp(`(?<!:)\\.${name}\\s*\\(`, "g"), `:${name}(`);
137
+ }
138
+ return next;
139
+ }
140
+
141
+ function rewritePlayerTemplateCtor(luau: string): string {
142
+ if (!/const TemplateData = require\(/.test(luau)) {
70
143
  return luau;
71
144
  }
72
- return insertAfterHeader(luau, 'const ReplicatedStorage = game:GetService("ReplicatedStorage")');
145
+ return String(luau).replace(/\bPlayerTemplate\s*\(/g, "TemplateData(");
146
+ }
147
+
148
+ export function rewriteClppEmit(luau: string): string {
149
+ let next = rewriteRosterNew(luau);
150
+ next = rewriteHiveWorldType(next);
151
+ next = rewriteCFrameColon(next);
152
+ next = rewriteCamelColon(next);
153
+ next = rewritePlayerTemplateCtor(next);
154
+ next = rewriteSweepJanitor(next);
155
+ next = rewriteGetServiceLuau(next);
156
+ next = rewriteReplicatedStorageRequires(next);
157
+ next = ensureReplicatedStorage(next);
158
+ const stamp = "-- cluaupp: Roster.new / GetService ReplicatedStorage / self.janitor";
159
+ if (!next.includes(stamp)) {
160
+ next = insertAfterHeader(next, stamp);
161
+ }
162
+ return formatLuauRoblox(next);
163
+ }
164
+
165
+ function ensureReplicatedStorage(luau: string): string {
166
+ return ensureGameServices(luau);
73
167
  }
74
168
 
75
169
  function stripInitCall(luau: string): string {
@@ -142,7 +236,8 @@ export function shouldSkipInit(fileName: string, hasSiblingHeader: boolean): boo
142
236
 
143
237
  export function clppLuauToGame(artifact: CompileArtifact, options: PostprocessOptions): string {
144
238
  let luau = rewriteClppLibs(artifact.luau || "", options.relativeName);
145
- luau = ensureReplicatedStorage(luau);
239
+ luau = rewriteClppEmit(luau);
240
+ luau = applyNativeHintsToLuau(luau, options.nativeHints || artifact.nativeHints);
146
241
  if (options.skipInit) {
147
242
  luau = stripInitCall(luau);
148
243
  }
@@ -0,0 +1,156 @@
1
+ const HEADER =
2
+ /^(?:const function |function )([A-Za-z0-9_]+)(?::([A-Za-z0-9_]+))?\(([^)]*)\)[^\n]*\n/gm;
3
+
4
+ const INSTANCE_TYPES = new Set([
5
+ "Instance",
6
+ "Part",
7
+ "BasePart",
8
+ "Model",
9
+ "Player",
10
+ "ScreenGui",
11
+ "GuiObject",
12
+ "TextButton",
13
+ "TextLabel",
14
+ "ImageLabel",
15
+ "Frame",
16
+ "Tool",
17
+ "Humanoid",
18
+ "Folder",
19
+ "ValueBase",
20
+ "IntValue",
21
+ "StringValue",
22
+ "BoolValue",
23
+ ]);
24
+
25
+ type Param = { name: string; type: string };
26
+
27
+ function parseParams(sig: string): Param[] {
28
+ const out: Param[] = [];
29
+ for (const piece of String(sig).split(",")) {
30
+ const match = piece.trim().match(/^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_]*)/);
31
+ if (match) {
32
+ out.push({ name: match[1], type: match[2] });
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+
38
+ function connectRoots(body: string): string[] {
39
+ const roots: string[] = [];
40
+ const seen = new Set<string>();
41
+ const re = /__janitor:Add\(([A-Za-z_][A-Za-z0-9_]*)/g;
42
+ let match: RegExpExecArray | null = re.exec(body);
43
+ while (match) {
44
+ const name = match[1];
45
+ if (!seen.has(name)) {
46
+ seen.add(name);
47
+ roots.push(name);
48
+ }
49
+ match = re.exec(body);
50
+ }
51
+ return roots;
52
+ }
53
+
54
+ function linkTarget(params: Param[], body: string): string | null {
55
+ const roots = connectRoots(body);
56
+ for (const root of roots) {
57
+ const param = params.find((item) => item.name === root && INSTANCE_TYPES.has(item.type));
58
+ if (param) {
59
+ return param.name;
60
+ }
61
+ }
62
+ const fallback = params.find((item) => INSTANCE_TYPES.has(item.type));
63
+ return fallback ? fallback.name : null;
64
+ }
65
+
66
+ function splitSelfGuard(body: string): { guard: string; rest: string } {
67
+ const match = body.match(/^(\tif not \(self[\s\S]*?\n\tend\n)/);
68
+ if (!match) {
69
+ return { guard: "", rest: body };
70
+ }
71
+ return { guard: match[1], rest: body.slice(match[1].length) };
72
+ }
73
+
74
+ function hoistSelf(): string {
75
+ return [
76
+ "\tlocal __janitor = self.janitor",
77
+ "\tif not __janitor then",
78
+ "\t\t__janitor = Janitor.new()",
79
+ "\t\tself.janitor = __janitor",
80
+ "\tend",
81
+ "",
82
+ ].join("\n");
83
+ }
84
+
85
+ function hoistLink(name: string): string {
86
+ return ["\tlocal __janitor = Janitor.new()", `\t__janitor:LinkToInstance(${name})`, ""].join("\n");
87
+ }
88
+
89
+ function hoistModule(): string {
90
+ return [
91
+ "\tif not __cluauppSweep then",
92
+ "\t\t__cluauppSweep = Janitor.new()",
93
+ "\tend",
94
+ "\tlocal __janitor = __cluauppSweep",
95
+ "",
96
+ ].join("\n");
97
+ }
98
+
99
+ function rewriteBody(params: string, body: string, isMethod: boolean): { body: string; moduleSweep: boolean } {
100
+ if (!/^[ \t]*local __janitor = Janitor\.new\(\)\s*\n/m.test(body)) {
101
+ return { body, moduleSweep: false };
102
+ }
103
+ if (/__janitor:LinkToInstance\(/.test(body)) {
104
+ return { body, moduleSweep: false };
105
+ }
106
+ const stripped = body.replace(/^[ \t]*local __janitor = Janitor\.new\(\)\s*\n/m, "");
107
+ const parsed = parseParams(params);
108
+ const link = linkTarget(parsed, stripped);
109
+ if (link) {
110
+ const pieces = splitSelfGuard(stripped);
111
+ return { body: `${pieces.guard}${hoistLink(link)}${pieces.rest}`, moduleSweep: false };
112
+ }
113
+ if (isMethod) {
114
+ const pieces = splitSelfGuard(stripped);
115
+ return { body: `${pieces.guard}${hoistSelf()}${pieces.rest}`, moduleSweep: false };
116
+ }
117
+ const pieces = splitSelfGuard(stripped);
118
+ return { body: `${pieces.guard}${hoistModule()}${pieces.rest}`, moduleSweep: true };
119
+ }
120
+
121
+ export function rewriteSweepJanitor(luau: string): string {
122
+ const source = String(luau);
123
+ HEADER.lastIndex = 0;
124
+ const matches = [...source.matchAll(HEADER)];
125
+ if (matches.length === 0) {
126
+ return source;
127
+ }
128
+
129
+ let out = source.slice(0, matches[0].index);
130
+ let needsModule = false;
131
+ for (let i = 0; i < matches.length; i += 1) {
132
+ const match = matches[i];
133
+ const header = match[0];
134
+ const method = match[2];
135
+ const params = match[3] || "";
136
+ const isMethod = Boolean(method);
137
+ const bodyStart = (match.index || 0) + header.length;
138
+ const bodyEnd = i + 1 < matches.length ? (matches[i + 1].index as number) : source.length;
139
+ const rawBody = source.slice(bodyStart, bodyEnd);
140
+ const rewritten = rewriteBody(params, rawBody, isMethod);
141
+ if (rewritten.moduleSweep) {
142
+ needsModule = true;
143
+ }
144
+ out += header + rewritten.body;
145
+ }
146
+
147
+ if (needsModule && !/\blocal __cluauppSweep\b/.test(out)) {
148
+ const inject = "local __cluauppSweep = nil\n";
149
+ if (/const Janitor = require[^\n]*\n/.test(out)) {
150
+ out = out.replace(/const Janitor = require[^\n]*\n/, (line) => `${line}${inject}`);
151
+ } else {
152
+ out = inject + out;
153
+ }
154
+ }
155
+ return out;
156
+ }
@@ -30,11 +30,11 @@ function cmpSemver(a: Semver, b: Semver): number {
30
30
  }
31
31
 
32
32
  function minClpp(): Semver {
33
- return parseSemver(MIN_CLPP_VERSION) || { major: 0, minor: 3, patch: 2 };
33
+ return parseSemver(MIN_CLPP_VERSION) || { major: 0, minor: 8, patch: 0 };
34
34
  }
35
35
 
36
36
  function tooOldMessage(bin: string, version: string | null): string {
37
- return `cluaupp: clpp ${version || "unknown"} is too old (${bin}). Need CL++ ${MIN_CLPP_VERSION}+. Install https://github.com/KartzRbx/CLPP/releases/download/v0.3.2/clpp-setup.exe or set CLPP / CLPP_PATH.`;
37
+ return `cluaupp: clpp ${version || "unknown"} is too old (${bin}). Need CL++ ${MIN_CLPP_VERSION}+. Install https://github.com/KartzRbx/CLPP/releases or set CLPP / CLPP_PATH.`;
38
38
  }
39
39
 
40
40
  function probeVersion(bin: string): string | null {
@@ -184,6 +184,12 @@ export function compileViaClpp(request: CompileRequest): CompileArtifact {
184
184
  source: request.source,
185
185
  fileName: request.fileName,
186
186
  strict: request.strict ?? null,
187
+ optimize: request.optimize ?? true,
188
+ targetProfilePath: request.targetProfilePath ?? null,
189
+ targetCacheDir: request.targetCacheDir ?? null,
190
+ runContext: request.runContext ?? null,
191
+ capabilityProfilePath: request.capabilityProfilePath ?? null,
192
+ datamodelProfilePath: request.datamodelProfilePath ?? null,
187
193
  });
188
194
  const result = spawnSync(bin, ["api", "compile"], {
189
195
  input: payload,
@@ -237,6 +243,12 @@ export function compileViaClppAsync(request: CompileRequest): Promise<CompileArt
237
243
  source: request.source,
238
244
  fileName: request.fileName,
239
245
  strict: request.strict ?? null,
246
+ optimize: request.optimize ?? true,
247
+ targetProfilePath: request.targetProfilePath ?? null,
248
+ targetCacheDir: request.targetCacheDir ?? null,
249
+ runContext: request.runContext ?? null,
250
+ capabilityProfilePath: request.capabilityProfilePath ?? null,
251
+ datamodelProfilePath: request.datamodelProfilePath ?? null,
240
252
  }),
241
253
  );
242
254
  });
package/src/compile.ts CHANGED
@@ -1,9 +1,65 @@
1
1
  import path from "node:path";
2
+ import fs from "node:fs";
2
3
  import type { CompileOptions, CompileServiceResult } from "./types.js";
3
4
  import { compileViaClpp, compileViaClppAsync } from "./clpp/runner.js";
4
5
  import { clppLuauToGame, shouldSkipInit } from "./clpp/postprocess.js";
5
6
  import { emitKind, siblingHeader, toLuauPath } from "./clpp/paths.js";
6
7
  import type { CompileArtifact } from "./clpp/contract.js";
8
+ import { projectRoot } from "./package-info.js";
9
+ import { runContextFromFileName } from "./target/roblox.js";
10
+ import { capabilityProfilePath, writeCapabilityProfile, loadCapabilityProfile } from "./target/capability-profile.js";
11
+ import { assertContextSafe, listContextWarnings, formatContextViolations } from "./target/context-check.js";
12
+ import { buildDatamodelProfile } from "./target/datamodel.js";
13
+ import { assertDatamodelSafe } from "./target/datamodel-check.js";
14
+ import { writeDatamodelArtifacts } from "./target/datamodel-generate.js";
15
+ import { assertParallelSafe } from "./target/parallel-check.js";
16
+ import { assertAuthoritySafe, loadPlatformPolicy } from "./target/authority-check.js";
17
+ import { assertGetServiceSafe } from "./target/get-service.js";
18
+
19
+ function defaultTargetProfilePath(): string | undefined {
20
+ const cached = path.join(projectRoot, "api", "normalized", "roblox-target.profile.json");
21
+ if (fs.existsSync(cached)) {
22
+ return cached.replace(/\\/g, "/");
23
+ }
24
+ return undefined;
25
+ }
26
+
27
+ function ensureCapabilityProfile(): string {
28
+ const file = capabilityProfilePath();
29
+ if (!fs.existsSync(file)) {
30
+ writeCapabilityProfile();
31
+ }
32
+ return file.replace(/\\/g, "/");
33
+ }
34
+
35
+ function resolveGameRoot(options: CompileOptions): string {
36
+ const start = options.rootDir
37
+ ? path.resolve(options.rootDir)
38
+ : options.filePath
39
+ ? path.dirname(path.resolve(options.filePath))
40
+ : process.cwd();
41
+ let dir = start;
42
+ for (let i = 0; i < 8; i++) {
43
+ if (fs.existsSync(path.join(dir, "default.project.json")) || fs.existsSync(path.join(dir, "default.project.jsonc"))) {
44
+ return dir;
45
+ }
46
+ const parent = path.dirname(dir);
47
+ if (parent === dir) {
48
+ break;
49
+ }
50
+ dir = parent;
51
+ }
52
+ return options.rootDir ? path.resolve(options.rootDir) : process.cwd();
53
+ }
54
+
55
+ function ensureDatamodel(options: CompileOptions): { profilePath?: string; profile: ReturnType<typeof buildDatamodelProfile> } {
56
+ const root = resolveGameRoot(options);
57
+ const written = writeDatamodelArtifacts(root);
58
+ if (written) {
59
+ return { profilePath: written.profilePath.replace(/\\/g, "/"), profile: written.profile };
60
+ }
61
+ return { profile: buildDatamodelProfile(root) };
62
+ }
7
63
 
8
64
  function compileArgs(source: string, fileName: string | undefined, options: CompileOptions) {
9
65
  const relative = (options.relativeName || fileName || "input.clpp").replace(/\\/g, "/");
@@ -11,20 +67,47 @@ function compileArgs(source: string, fileName: string | undefined, options: Comp
11
67
  const header = options.filePath ? siblingHeader(options.filePath) : null;
12
68
  const skipInit = options.skipInit === true || shouldSkipInit(relative, Boolean(header));
13
69
  const diskPath = options.filePath ? path.resolve(options.filePath) : null;
70
+ const runContext = runContextFromFileName(relative);
71
+ const dm = ensureDatamodel(options);
72
+ const gameRoot = resolveGameRoot(options);
14
73
  return {
15
74
  request: {
16
75
  source,
17
76
  fileName: diskPath ? diskPath.replace(/\\/g, "/") : relative,
18
77
  strict: options.strict,
78
+ optimize: options.optimize !== false,
19
79
  cwd: diskPath ? path.dirname(diskPath) : options.srcDir,
80
+ targetProfilePath: defaultTargetProfilePath(),
81
+ targetCacheDir: path.join(projectRoot, "api", ".cache").replace(/\\/g, "/"),
82
+ runContext,
83
+ capabilityProfilePath: ensureCapabilityProfile(),
84
+ datamodelProfilePath: dm.profilePath,
20
85
  },
21
86
  relative,
22
87
  outName,
23
88
  skipInit,
24
89
  options,
90
+ datamodel: dm.profile,
91
+ gameRoot,
92
+ policy: loadPlatformPolicy(gameRoot),
25
93
  };
26
94
  }
27
95
 
96
+ function enforcePlatform(source: string, relative: string, args: ReturnType<typeof compileArgs>): void {
97
+ const profile = loadCapabilityProfile();
98
+ assertContextSafe(source, relative, profile);
99
+ const warnings = listContextWarnings(source, relative, profile);
100
+ if (warnings.length) {
101
+ console.warn(formatContextViolations(relative, warnings));
102
+ }
103
+ if (args.datamodel) {
104
+ assertDatamodelSafe(source, args.datamodel);
105
+ }
106
+ assertParallelSafe(source, relative);
107
+ assertAuthoritySafe(source, relative, args.policy);
108
+ assertGetServiceSafe(source, relative);
109
+ }
110
+
28
111
  function finishArtifact(
29
112
  artifact: CompileArtifact,
30
113
  relative: string,
@@ -41,6 +124,8 @@ function finishArtifact(
41
124
  strict: options.strict,
42
125
  skipInit,
43
126
  source,
127
+ nativeHints: artifact.nativeHints,
128
+ layoutHints: artifact.layoutHints,
44
129
  });
45
130
  return {
46
131
  kind: emitKind(relative),
@@ -56,12 +141,14 @@ export function compileSource(source: string, fileName?: string, options: Compil
56
141
 
57
142
  export function compileService(source: string, fileName?: string, options: CompileOptions = {}): CompileServiceResult {
58
143
  const args = compileArgs(source, fileName, options);
144
+ enforcePlatform(source, args.relative, args);
59
145
  const artifact = compileViaClpp(args.request);
60
146
  return finishArtifact(artifact, args.relative, args.outName, args.options, args.skipInit, source);
61
147
  }
62
148
 
63
149
  export async function compileServiceAsync(source: string, fileName?: string, options: CompileOptions = {}): Promise<CompileServiceResult> {
64
150
  const args = compileArgs(source, fileName, options);
151
+ enforcePlatform(source, args.relative, args);
65
152
  const artifact = await compileViaClppAsync(args.request);
66
153
  return finishArtifact(artifact, args.relative, args.outName, args.options, args.skipInit, source);
67
154
  }
@@ -76,6 +76,7 @@ function parseSide(raw: string, file: string, line: number): FlareSide {
76
76
  export function parseFlare(source: string, filePath: string, defaultName: string): FlareSchema {
77
77
  const file = filePath.replace(/\\/g, "/");
78
78
  let name = defaultName;
79
+ let version: number | undefined;
79
80
  const packets: FlarePacket[] = [];
80
81
  const queries: FlareQuery[] = [];
81
82
  let packetId = 1;
@@ -89,6 +90,12 @@ export function parseFlare(source: string, filePath: string, defaultName: string
89
90
  continue;
90
91
  }
91
92
 
93
+ const verStmt = line.match(/^version\s+(\d+)\s*;?$/i);
94
+ if (verStmt) {
95
+ version = Number(verStmt[1]);
96
+ continue;
97
+ }
98
+
92
99
  const opt = line.match(/^opt\s+name\s*=\s*(.+)$/i);
93
100
  if (opt) {
94
101
  const value = opt[1].trim().replace(/^["']|["']$/g, "");
@@ -99,6 +106,12 @@ export function parseFlare(source: string, filePath: string, defaultName: string
99
106
  continue;
100
107
  }
101
108
 
109
+ const optVer = line.match(/^opt\s+version\s*=\s*(\d+)\s*;?$/i);
110
+ if (optVer) {
111
+ version = Number(optVer[1]);
112
+ continue;
113
+ }
114
+
102
115
  const packet = line.match(
103
116
  new RegExp(
104
117
  `^packet\\s+(${FLARE_IDENT})\\s*\\((.*)\\)\\s+from\\s+(Client|Server)(?:\\s+(unreliable|reliable))?\\s*$`,
@@ -143,5 +156,5 @@ export function parseFlare(source: string, filePath: string, defaultName: string
143
156
  fail(file, 1, "schema is empty — add a packet or query");
144
157
  }
145
158
 
146
- return { name, sourcePath: file, packets, queries };
159
+ return { name, sourcePath: file, version, packets, queries };
147
160
  }
@@ -48,6 +48,8 @@ export type FlareQuery = {
48
48
  export type FlareSchema = {
49
49
  name: string;
50
50
  sourcePath: string;
51
+ /** Optional schema version from `version N;` / `opt version = N`. */
52
+ version?: number;
51
53
  packets: FlarePacket[];
52
54
  queries: FlareQuery[];
53
55
  };
@@ -7,6 +7,7 @@ import type { ProjectConfig } from "./types.js";
7
7
  import { CLPP_INSTALL_HINT } from "./clpp/contract.js";
8
8
  import { hasClpp } from "./clpp/runner.js";
9
9
  import { isSourceFile } from "./clpp/paths.js";
10
+ import { editorBin } from "./editor-install.js";
10
11
 
11
12
  export type CluauppDiagnostic = {
12
13
  line: number;
@@ -83,10 +84,24 @@ function writeVscode(root: string): void {
83
84
  "*.client.clpp": "clpp",
84
85
  "*.plugin.clpp": "clpp",
85
86
  "*.flare": "flare",
87
+ "*.hive": "hive",
88
+ "*.mint": "mint",
89
+ "*.bloom": "bloom",
90
+ "*.helm": "helm",
91
+ "*.shift": "shift",
92
+ "*.axiom": "axiom",
86
93
  };
87
94
  writeJson(settingsPath, {
88
95
  ...current,
89
96
  "files.associations": associations,
97
+ "[luau]": {
98
+ ...((current["[luau]"] && typeof current["[luau]"] === "object" && !Array.isArray(current["[luau]"]))
99
+ ? (current["[luau]"] as Record<string, unknown>)
100
+ : {}),
101
+ "editor.insertSpaces": false,
102
+ "editor.tabSize": 4,
103
+ "editor.detectIndentation": false,
104
+ },
90
105
  });
91
106
 
92
107
  const extensionsPath = path.join(root, ".vscode", "extensions.json");
@@ -104,8 +119,32 @@ export function diagnosticsFor(_source?: string, _fileName?: string): CluauppDia
104
119
  return [];
105
120
  }
106
121
 
122
+ function writeStylua(root: string): void {
123
+ const dest = path.join(root, "stylua.toml");
124
+ const body = `# cluaupp roblox luau
125
+ syntax = "Luau"
126
+ column_width = 120
127
+ line_endings = "Unix"
128
+ indent_type = "Tabs"
129
+ indent_width = 4
130
+ quote_style = "AutoPreferDouble"
131
+ call_parentheses = "Always"
132
+ collapse_simple_statement = "Never"
133
+ `;
134
+ if (fs.existsSync(dest)) {
135
+ const existing = fs.readFileSync(dest, "utf8");
136
+ if (!existing.includes("cluaupp roblox luau") && existing.trim() !== "") {
137
+ return;
138
+ }
139
+ }
140
+ if (!fs.existsSync(dest) || fs.readFileSync(dest, "utf8") !== body) {
141
+ fs.writeFileSync(dest, body, "utf8");
142
+ }
143
+ }
144
+
107
145
  export function syncEditorSupport(root: string, _config: Partial<ProjectConfig> = {}): void {
108
146
  writeVscode(root);
147
+ writeStylua(root);
109
148
  }
110
149
 
111
150
  export function installEditorExtension(cluauppRoot = PACKAGE_ROOT): string[] {
@@ -121,6 +160,15 @@ export function installEditorExtension(cluauppRoot = PACKAGE_ROOT): string[] {
121
160
  continue;
122
161
  }
123
162
  fs.mkdirSync(home, { recursive: true });
163
+ try {
164
+ for (const name of fs.readdirSync(home)) {
165
+ if (name.startsWith("kartzdev.cluaupp-flare-") && name !== id) {
166
+ fs.rmSync(path.join(home, name), { recursive: true, force: true });
167
+ }
168
+ }
169
+ } catch {
170
+ // ignore prune errors
171
+ }
124
172
  const dest = path.join(home, id);
125
173
  copyDir(from, dest);
126
174
  fs.writeFileSync(path.join(dest, "cluaupp.root"), path.resolve(cluauppRoot), "utf8");
@@ -136,13 +184,22 @@ export function installEditorExtension(cluauppRoot = PACKAGE_ROOT): string[] {
136
184
  }
137
185
  installed.push(dest);
138
186
  }
187
+
188
+ const bin = editorBin();
189
+ if (bin && installed[0]) {
190
+ spawnSync(bin, ["--install-extension", installed[0], "--force"], {
191
+ encoding: "utf8",
192
+ windowsHide: true,
193
+ timeout: 120000,
194
+ });
195
+ }
139
196
  return installed;
140
197
  }
141
198
 
142
199
  export async function installEditorSupport() {
143
200
  const local = installEditorExtension();
144
201
  if (local.length > 0) {
145
- console.log("cluaupp: Flare IntelliSense installed");
202
+ console.log("cluaupp: schema IntelliSense installed (.flare .hive .mint .bloom .helm .shift .axiom)");
146
203
  for (const dest of local) {
147
204
  console.log(" ", dest);
148
205
  }