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
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Parallel Luau / ThreadSafety diagnostics (CLUAU-PAR*).
3
+ * Flags Unsafe mutations inside parallel { } / desynchronize regions.
4
+ */
5
+
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { projectRoot } from "../package-info.js";
9
+ import type { RobloxTargetProfile, ThreadSafety } from "../api/model.js";
10
+ import { type PlatformDiagnostic, lineColAt, stripCommentsKeepStrings } from "./diagnostics.js";
11
+
12
+ let cachedUnsafeMembers: Set<string> | null = null;
13
+
14
+ function loadUnsafeMemberNames(): Set<string> {
15
+ if (cachedUnsafeMembers) {
16
+ return cachedUnsafeMembers;
17
+ }
18
+ const set = new Set<string>(["Parent", "Name"]); // Parent writes always unsafe in parallel
19
+ const profilePath = path.join(projectRoot, "api", "normalized", "roblox-target.profile.json");
20
+ if (fs.existsSync(profilePath)) {
21
+ try {
22
+ const profile = JSON.parse(fs.readFileSync(profilePath, "utf8")) as RobloxTargetProfile;
23
+ for (const cls of Object.values(profile.classes || {})) {
24
+ for (const prop of Object.values(cls.properties || {})) {
25
+ if (prop.threadSafety === "Unsafe") {
26
+ set.add(prop.name);
27
+ }
28
+ }
29
+ for (const method of Object.values(cls.methods || {})) {
30
+ if (method.threadSafety === "Unsafe") {
31
+ set.add(method.name);
32
+ }
33
+ }
34
+ }
35
+ } catch {
36
+ /* fallback set only */
37
+ }
38
+ }
39
+ cachedUnsafeMembers = set;
40
+ return set;
41
+ }
42
+
43
+ function extractParallelRegions(source: string): Array<{ start: number; body: string }> {
44
+ const regions: Array<{ start: number; body: string }> = [];
45
+ const reParallel = /\bparallel\s*\{/g;
46
+ let m: RegExpExecArray | null;
47
+ while ((m = reParallel.exec(source))) {
48
+ const open = m.index + m[0].length - 1;
49
+ let depth = 0;
50
+ for (let i = open; i < source.length; i++) {
51
+ if (source[i] === "{") depth++;
52
+ else if (source[i] === "}") {
53
+ depth--;
54
+ if (depth === 0) {
55
+ regions.push({ start: m.index, body: source.slice(open + 1, i) });
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ }
61
+ const reDesync = /task\s*::\s*desynchronize\s*\(\s*\)/g;
62
+ while ((m = reDesync.exec(source))) {
63
+ const rest = source.slice(m.index);
64
+ const sync = rest.search(/task\s*::\s*synchronize\s*\(\s*\)/);
65
+ const body = sync >= 0 ? rest.slice(0, sync) : rest.slice(0, Math.min(rest.length, 800));
66
+ regions.push({ start: m.index, body });
67
+ }
68
+ if (/\bConnectParallel\b/.test(source)) {
69
+ regions.push({ start: source.indexOf("ConnectParallel"), body: source });
70
+ }
71
+ return regions;
72
+ }
73
+
74
+ export function checkParallelSafety(source: string, fileName = "input.clpp"): PlatformDiagnostic[] {
75
+ const clean = stripCommentsKeepStrings(source);
76
+ const unsafe = loadUnsafeMemberNames();
77
+ const out: PlatformDiagnostic[] = [];
78
+ const regions = extractParallelRegions(clean);
79
+ if (!regions.length) {
80
+ return out;
81
+ }
82
+ for (const region of regions) {
83
+ const parentAssign = /\.Parent\s*=/g;
84
+ let pm: RegExpExecArray | null;
85
+ while ((pm = parentAssign.exec(region.body))) {
86
+ const { line, column } = lineColAt(clean, region.start + pm.index);
87
+ out.push({
88
+ code: "CLUAU_PAR001",
89
+ message: "Unsafe Instance write `.Parent =` inside parallel / desynchronized region",
90
+ line,
91
+ column,
92
+ severity: "error",
93
+ file: fileName,
94
+ });
95
+ }
96
+ const memberWrite = /\.([A-Za-z_]\w*)\s*=/g;
97
+ while ((pm = memberWrite.exec(region.body))) {
98
+ const name = pm[1];
99
+ if (name === "Parent") continue;
100
+ if (!unsafe.has(name)) continue;
101
+ const { line, column } = lineColAt(clean, region.start + pm.index);
102
+ out.push({
103
+ code: "CLUAU_PAR002",
104
+ message: `API member \`.${name}\` is ThreadSafety=Unsafe inside parallel region`,
105
+ line,
106
+ column,
107
+ severity: "error",
108
+ file: fileName,
109
+ });
110
+ }
111
+ const destroy = /\.Destroy\s*\(/g;
112
+ while ((pm = destroy.exec(region.body))) {
113
+ const { line, column } = lineColAt(clean, region.start + pm.index);
114
+ out.push({
115
+ code: "CLUAU_PAR003",
116
+ message: "`Destroy()` is Unsafe inside parallel region",
117
+ line,
118
+ column,
119
+ severity: "error",
120
+ file: fileName,
121
+ });
122
+ }
123
+ }
124
+ return out;
125
+ }
126
+
127
+ export function assertParallelSafe(source: string, fileName?: string): void {
128
+ const errors = checkParallelSafety(source, fileName).filter((d) => d.severity === "error");
129
+ if (!errors.length) return;
130
+ throw new Error(
131
+ `Parallel safety:\n${errors.map((e) => ` ${e.line}:${e.column} ${e.code} ${e.message}`).join("\n")}`,
132
+ );
133
+ }
134
+
135
+ export type { ThreadSafety };
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Profile-Guided Optimization (PGO) — format, load, Studio ingest.
3
+ * cluaupp.profile.json weights optimizer advice toward hot symbols.
4
+ */
5
+
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import type { OptimizeAdvice } from "./optimizer-advise.js";
9
+
10
+ export const PGO_SCHEMA_VERSION = 1 as const;
11
+
12
+ export interface CluauppProfile {
13
+ schemaVersion: typeof PGO_SCHEMA_VERSION;
14
+ generatedAt?: string;
15
+ /** Symbol / function name → call counts (or relative weight). */
16
+ hot: Record<string, number>;
17
+ /** Optional struct names observed as hot. */
18
+ structs?: Record<string, number>;
19
+ }
20
+
21
+ /** One Studio / playtest hit — JSONL or JSON array. */
22
+ export interface ProfileEvent {
23
+ symbol: string;
24
+ kind?: "hot" | "struct";
25
+ count?: number;
26
+ }
27
+
28
+ export function defaultProfilePath(projectRoot: string): string {
29
+ return path.join(projectRoot, "cluaupp.profile.json");
30
+ }
31
+
32
+ export function loadProfile(file: string): CluauppProfile | null {
33
+ if (!fs.existsSync(file)) {
34
+ return null;
35
+ }
36
+ try {
37
+ const raw = JSON.parse(fs.readFileSync(file, "utf8")) as CluauppProfile;
38
+ if (!raw || typeof raw.hot !== "object") {
39
+ return null;
40
+ }
41
+ return { schemaVersion: PGO_SCHEMA_VERSION, hot: raw.hot, structs: raw.structs, generatedAt: raw.generatedAt };
42
+ } catch {
43
+ return null;
44
+ }
45
+ }
46
+
47
+ /** Write an empty / template profile for games to fill from Studio logging. */
48
+ export function writeProfileTemplate(projectRoot: string): string {
49
+ const file = defaultProfilePath(projectRoot);
50
+ const template: CluauppProfile = {
51
+ schemaVersion: PGO_SCHEMA_VERSION,
52
+ generatedAt: new Date().toISOString(),
53
+ hot: {
54
+ CalculateDamage: 0,
55
+ EnemyUpdate: 0,
56
+ },
57
+ structs: {
58
+ EnemyState: 0,
59
+ },
60
+ };
61
+ fs.writeFileSync(file, JSON.stringify(template, null, "\t") + "\n", "utf8");
62
+ return file;
63
+ }
64
+
65
+ function parseEvents(raw: string): ProfileEvent[] {
66
+ const trimmed = raw.trim();
67
+ if (!trimmed) return [];
68
+ if (trimmed.startsWith("[")) {
69
+ const arr = JSON.parse(trimmed) as unknown;
70
+ if (!Array.isArray(arr)) return [];
71
+ return arr.filter((e) => e && typeof (e as ProfileEvent).symbol === "string") as ProfileEvent[];
72
+ }
73
+ if (trimmed.startsWith("{") && !trimmed.includes("\n")) {
74
+ const one = JSON.parse(trimmed) as Record<string, unknown>;
75
+ if (typeof one.symbol === "string") {
76
+ return [one as unknown as ProfileEvent];
77
+ }
78
+ if (one.hot && typeof one.hot === "object") {
79
+ return Object.entries(one.hot as Record<string, number>).map(([symbol, count]) => ({
80
+ symbol,
81
+ kind: "hot" as const,
82
+ count: Number(count) || 0,
83
+ }));
84
+ }
85
+ }
86
+ const events: ProfileEvent[] = [];
87
+ for (const line of trimmed.split(/\r?\n/)) {
88
+ const t = line.trim();
89
+ if (!t || t.startsWith("#")) continue;
90
+ try {
91
+ const e = JSON.parse(t) as ProfileEvent;
92
+ if (e && typeof e.symbol === "string") events.push(e);
93
+ } catch {
94
+ /* skip bad line */
95
+ }
96
+ }
97
+ return events;
98
+ }
99
+
100
+ /** Merge Studio/playtest events into cluaupp.profile.json (additive counts). */
101
+ export function ingestProfile(
102
+ projectRoot: string,
103
+ eventsPath: string,
104
+ ): { profilePath: string; profile: CluauppProfile; merged: number } {
105
+ const eventsFile = path.resolve(eventsPath);
106
+ if (!fs.existsSync(eventsFile)) {
107
+ throw new Error(`cluaupp profile ingest: missing ${eventsFile}`);
108
+ }
109
+ const events = parseEvents(fs.readFileSync(eventsFile, "utf8"));
110
+ const profilePath = defaultProfilePath(projectRoot);
111
+ const existing = loadProfile(profilePath) || {
112
+ schemaVersion: PGO_SCHEMA_VERSION,
113
+ hot: {},
114
+ structs: {},
115
+ };
116
+ const hot = { ...(existing.hot || {}) };
117
+ const structs = { ...(existing.structs || {}) };
118
+ let merged = 0;
119
+ for (const e of events) {
120
+ const n = typeof e.count === "number" && Number.isFinite(e.count) ? e.count : 1;
121
+ if (e.kind === "struct") {
122
+ structs[e.symbol] = (structs[e.symbol] || 0) + n;
123
+ } else {
124
+ hot[e.symbol] = (hot[e.symbol] || 0) + n;
125
+ }
126
+ merged++;
127
+ }
128
+ const profile: CluauppProfile = {
129
+ schemaVersion: PGO_SCHEMA_VERSION,
130
+ generatedAt: new Date().toISOString(),
131
+ hot,
132
+ structs,
133
+ };
134
+ fs.writeFileSync(profilePath, JSON.stringify(profile, null, "\t") + "\n", "utf8");
135
+ return { profilePath, profile, merged };
136
+ }
137
+
138
+ export function rankAdvice(advice: OptimizeAdvice[], profile: CluauppProfile | null): OptimizeAdvice[] {
139
+ if (!profile) {
140
+ return advice;
141
+ }
142
+ return [...advice]
143
+ .sort((a, b) => {
144
+ const wa = profile.hot[a.target] || profile.structs?.[a.target] || 0;
145
+ const wb = profile.hot[b.target] || profile.structs?.[b.target] || 0;
146
+ return wb - wa;
147
+ })
148
+ .map((a) => {
149
+ const w = profile.hot[a.target] || profile.structs?.[a.target];
150
+ if (!w) return a;
151
+ return {
152
+ ...a,
153
+ message: `${a.message} [PGO weight=${w}]`,
154
+ severity: w > 1000 ? "warning" : a.severity,
155
+ };
156
+ });
157
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Generate project documentation from DataModel + graph + Flare + advice.
3
+ */
4
+
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { buildDatamodelProfile } from "./datamodel.js";
8
+ import { buildProjectGraph } from "./project-graph.js";
9
+ import { checkFlareVersions } from "./flare-version.js";
10
+ import { collectSources } from "../clpp/paths.js";
11
+ import { adviseOptimizer } from "./optimizer-advise.js";
12
+
13
+ export function generateProjectDocs(projectRoot: string, rootDir = "src"): { outPath: string; markdown: string } {
14
+ const dm = buildDatamodelProfile(projectRoot);
15
+ const graph = buildProjectGraph(projectRoot, rootDir);
16
+ const flare = checkFlareVersions(projectRoot, rootDir);
17
+ const srcDir = path.join(projectRoot, rootDir);
18
+ const files = fs.existsSync(srcDir) ? collectSources(srcDir) : [];
19
+ const advice: string[] = [];
20
+ for (const file of files) {
21
+ const rel = path.relative(projectRoot, file).replace(/\\/g, "/");
22
+ for (const a of adviseOptimizer(fs.readFileSync(file, "utf8"), rel)) {
23
+ advice.push(`- **${a.target}** (${a.kind}): ${a.message}`);
24
+ }
25
+ }
26
+
27
+ const paths = dm
28
+ ? Object.keys(dm.byPath)
29
+ .filter((p) => p !== "DataModel")
30
+ .sort()
31
+ .map((p) => `- \`${p}\` — ${dm.byPath[p].className}`)
32
+ .join("\n")
33
+ : "_no default.project.json_";
34
+
35
+ const markdown = [
36
+ `# Cluaupp project docs`,
37
+ ``,
38
+ `Generated: ${new Date().toISOString()}`,
39
+ ``,
40
+ `## DataModel`,
41
+ ``,
42
+ paths,
43
+ ``,
44
+ `## Modules (${graph.nodes.length})`,
45
+ ``,
46
+ graph.nodes.map((n) => `- \`${n}\``).join("\n") || "_none_",
47
+ ``,
48
+ `## Dependencies`,
49
+ ``,
50
+ graph.edges.map((e) => `- \`${e.from}\` → \`${e.to}\``).join("\n") || "_none_",
51
+ ``,
52
+ graph.cycles.length ? `### Cycles\n\n${graph.cycles.map((c) => `- ${c.join(" → ")}`).join("\n")}\n` : "",
53
+ `## Flare contracts`,
54
+ ``,
55
+ flare.files.map((f) => `- \`${f.file}\` name=\`${f.name}\` version=${f.version ?? "unset"}`).join("\n") || "_none_",
56
+ ``,
57
+ `## Optimizer advice`,
58
+ ``,
59
+ advice.slice(0, 40).join("\n") || "_none_",
60
+ ``,
61
+ ].join("\n");
62
+
63
+ const outDir = path.join(projectRoot, ".cluaupp");
64
+ fs.mkdirSync(outDir, { recursive: true });
65
+ const outPath = path.join(outDir, "PROJECT.md");
66
+ fs.writeFileSync(outPath, markdown, "utf8");
67
+ return { outPath, markdown };
68
+ }
@@ -0,0 +1,75 @@
1
+ /** Project include/import/require graph + circular dependency detection. */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { collectLanguageModulePaths, resolveModuleFile } from "../clpp/modules.js";
5
+ import { collectSources } from "../clpp/paths.js";
6
+
7
+ export interface GraphEdge {
8
+ from: string;
9
+ to: string;
10
+ }
11
+
12
+ export interface ProjectGraph {
13
+ nodes: string[];
14
+ edges: GraphEdge[];
15
+ cycles: string[][];
16
+ }
17
+
18
+ function findCycles(nodes: string[], edges: GraphEdge[]): string[][] {
19
+ const adj = new Map<string, string[]>();
20
+ for (const n of nodes) adj.set(n, []);
21
+ for (const e of edges) {
22
+ if (!adj.has(e.from)) adj.set(e.from, []);
23
+ adj.get(e.from)!.push(e.to);
24
+ }
25
+ const cycles: string[][] = [];
26
+ const visiting = new Set<string>();
27
+ const visited = new Set<string>();
28
+ const stack: string[] = [];
29
+
30
+ function dfs(n: string) {
31
+ if (visiting.has(n)) {
32
+ const i = stack.indexOf(n);
33
+ if (i >= 0) cycles.push(stack.slice(i).concat(n));
34
+ return;
35
+ }
36
+ if (visited.has(n)) return;
37
+ visiting.add(n);
38
+ stack.push(n);
39
+ for (const to of adj.get(n) || []) dfs(to);
40
+ stack.pop();
41
+ visiting.delete(n);
42
+ visited.add(n);
43
+ }
44
+ for (const n of nodes) dfs(n);
45
+ return cycles;
46
+ }
47
+
48
+ export function buildProjectGraph(projectRoot: string, rootDir = "src"): ProjectGraph {
49
+ const srcDir = path.join(projectRoot, rootDir);
50
+ const files = fs.existsSync(srcDir) ? collectSources(srcDir) : [];
51
+ const nodes: string[] = [];
52
+ const edges: GraphEdge[] = [];
53
+ const byAbs = new Map<string, string>();
54
+
55
+ for (const file of files) {
56
+ const rel = path.relative(projectRoot, file).replace(/\\/g, "/");
57
+ nodes.push(rel);
58
+ byAbs.set(path.resolve(file), rel);
59
+ }
60
+
61
+ for (const file of files) {
62
+ const rel = path.relative(projectRoot, file).replace(/\\/g, "/");
63
+ const source = fs.readFileSync(file, "utf8");
64
+ for (const mod of collectLanguageModulePaths(source)) {
65
+ const resolved = resolveModuleFile(mod, file, srcDir);
66
+ if (!resolved) continue;
67
+ const hit = byAbs.get(path.resolve(resolved));
68
+ if (hit && hit !== rel) {
69
+ edges.push({ from: rel, to: hit });
70
+ }
71
+ }
72
+ }
73
+
74
+ return { nodes, edges, cycles: findCycles(nodes, edges) };
75
+ }
@@ -0,0 +1,78 @@
1
+ import type { RobloxTargetProfile } from "../api/model.js";
2
+ import { ROBLOX_TARGET_SCHEMA_VERSION } from "../api/model.js";
3
+ import { buildRobloxTargetProfile } from "../api/build-profile.js";
4
+
5
+ /** Cluaupp-owned run contexts — never push these into CLPP core. */
6
+ export type RunContext = "Server" | "Client" | "Plugin" | "Shared";
7
+
8
+ export const FILE_TAG_TO_CONTEXT: Record<string, RunContext> = {
9
+ ".server": "Server",
10
+ ".client": "Client",
11
+ ".plugin": "Plugin",
12
+ };
13
+
14
+ export function runContextFromFileName(fileName: string): RunContext {
15
+ const lower = fileName.toLowerCase();
16
+ if (lower.includes(".server.")) {
17
+ return "Server";
18
+ }
19
+ if (lower.includes(".client.")) {
20
+ return "Client";
21
+ }
22
+ if (lower.includes(".plugin.")) {
23
+ return "Plugin";
24
+ }
25
+ return "Shared";
26
+ }
27
+
28
+ export interface RobloxProjectModel {
29
+ kind: "roblox";
30
+ rojoProjectPath?: string;
31
+ libsFolderName: "CluauppLibs";
32
+ /** Historical CLPP postprocess name — remapped in Cluaupp only. */
33
+ legacyLibsAlias: "ClppLibs";
34
+ }
35
+
36
+ export function defaultRobloxProject(): RobloxProjectModel {
37
+ return {
38
+ kind: "roblox",
39
+ libsFolderName: "CluauppLibs",
40
+ legacyLibsAlias: "ClppLibs",
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Target-side GetService\<T\> — **Cluaupp Roblox Target feature**, not a CL++ language rule.
46
+ * CL++ only provides generic-call syntax (`GetService<Players>()`); Cluaupp maps T via the
47
+ * Canonical Registry, Context Safety, and headers under `#include <clpp/roblox.clh>`.
48
+ */
49
+ export function resolveGetServiceType(typeName: string, profile?: RobloxTargetProfile): string | null {
50
+ const p = profile || buildRobloxTargetProfile({ skipValidate: true });
51
+ if (p.services[typeName]) {
52
+ return typeName;
53
+ }
54
+ if (p.classes[typeName]?.service || p.classes[typeName]?.creation.service) {
55
+ return typeName;
56
+ }
57
+ return null;
58
+ }
59
+
60
+ /** True when `name` is a registered Roblox service class. */
61
+ export function isRegisteredService(name: string, profile?: RobloxTargetProfile): boolean {
62
+ return resolveGetServiceType(name, profile) != null;
63
+ }
64
+
65
+ export function targetProfileSummary(): {
66
+ schemaVersion: number;
67
+ target: "roblox";
68
+ classes: number;
69
+ services: number;
70
+ } {
71
+ const profile = buildRobloxTargetProfile({ skipValidate: true });
72
+ return {
73
+ schemaVersion: ROBLOX_TARGET_SCHEMA_VERSION,
74
+ target: "roblox",
75
+ classes: Object.keys(profile.classes).length,
76
+ services: Object.keys(profile.services).length,
77
+ };
78
+ }
@@ -0,0 +1,40 @@
1
+ /** Static security patterns (CLUAU-SEC*) — not a runtime anti-cheat. */
2
+ import { runContextFromFileName } from "./roblox.js";
3
+ import { type PlatformDiagnostic, lineColAt, stripCommentsKeepStrings } from "./diagnostics.js";
4
+
5
+ const CLIENT_PATTERNS: Array<{ code: string; re: RegExp; message: string }> = [
6
+ { code: "CLUAU_SEC001", re: /\bCoins\s*=/, message: "Client appears to assign Coins — server must own currency" },
7
+ { code: "CLUAU_SEC002", re: /\bDamage\s*=\s*[^=]/, message: "Client appears to set Damage — prefer server authority" },
8
+ { code: "CLUAU_SEC003", re: /FireServer\s*\([^)]*Instance/, message: "Remote may accept unrestricted Instance from client" },
9
+ { code: "CLUAU_SEC004", re: /Inventory.*=.*FireServer|FireServer.*Inventory/, message: "Client-supplied inventory result smell" },
10
+ ];
11
+
12
+ const SERVER_PATTERNS: Array<{ code: string; re: RegExp; message: string }> = [
13
+ { code: "CLUAU_SEC010", re: /FireServer/, message: "Server calling FireServer is inverted authority" },
14
+ {
15
+ code: "CLUAU_SEC011",
16
+ re: /\.Position\b[^\n]*player|player[^\n]*\.Position/,
17
+ message: "Server may be trusting client Position — validate or ignore client transform",
18
+ },
19
+ ];
20
+
21
+ export function checkSecurity(source: string, fileName: string): PlatformDiagnostic[] {
22
+ const ctx = runContextFromFileName(fileName);
23
+ const clean = stripCommentsKeepStrings(source);
24
+ const out: PlatformDiagnostic[] = [];
25
+ const list = ctx === "Client" ? CLIENT_PATTERNS : ctx === "Server" ? SERVER_PATTERNS : [];
26
+ for (const p of list) {
27
+ const m = p.re.exec(clean);
28
+ if (!m) continue;
29
+ const { line, column } = lineColAt(clean, m.index);
30
+ out.push({
31
+ code: p.code,
32
+ message: p.message,
33
+ line,
34
+ column,
35
+ severity: "warning",
36
+ file: fileName,
37
+ });
38
+ }
39
+ return out;
40
+ }
@@ -0,0 +1,36 @@
1
+ /** Minimal source map: CL++ path ↔ emitted Luau (1:1 file mapping for v1). */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+
5
+ export interface CluauppSourceMap {
6
+ version: 1;
7
+ file: string;
8
+ sourceRoot: string;
9
+ sources: string[];
10
+ mappings: string;
11
+ cluaupp: {
12
+ source: string;
13
+ generated: string;
14
+ };
15
+ }
16
+
17
+ export function writeSourceMap(opts: {
18
+ outLuauPath: string;
19
+ sourceClppRel: string;
20
+ projectRoot: string;
21
+ }): string {
22
+ const map: CluauppSourceMap = {
23
+ version: 1,
24
+ file: path.basename(opts.outLuauPath),
25
+ sourceRoot: opts.projectRoot.replace(/\\/g, "/"),
26
+ sources: [opts.sourceClppRel.replace(/\\/g, "/")],
27
+ mappings: "AAAA", // identity stub — refine when clpp emits VLQ maps
28
+ cluaupp: {
29
+ source: opts.sourceClppRel.replace(/\\/g, "/"),
30
+ generated: path.relative(opts.projectRoot, opts.outLuauPath).replace(/\\/g, "/"),
31
+ },
32
+ };
33
+ const mapPath = opts.outLuauPath + ".map.json";
34
+ fs.writeFileSync(mapPath, JSON.stringify(map, null, "\t") + "\n", "utf8");
35
+ return mapPath;
36
+ }