cluaupp 1.5.0 → 1.5.1

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 (323) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +10 -5
  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/data/Mini-API-Dump.json +1 -0
  25. package/editors/vscode/README.md +12 -10
  26. package/editors/vscode/extension.js +82 -0
  27. package/editors/vscode/icons/axiom.svg +4 -0
  28. package/editors/vscode/icons/bloom.svg +5 -0
  29. package/editors/vscode/icons/helm.svg +4 -0
  30. package/editors/vscode/icons/hive.svg +5 -0
  31. package/editors/vscode/icons/mint.svg +4 -0
  32. package/editors/vscode/icons/shift.svg +6 -0
  33. package/editors/vscode/language-configuration-schema.json +24 -0
  34. package/editors/vscode/package.json +172 -12
  35. package/editors/vscode/snippets/axiom.json +12 -0
  36. package/editors/vscode/snippets/bloom.json +12 -0
  37. package/editors/vscode/snippets/helm.json +12 -0
  38. package/editors/vscode/snippets/hive.json +12 -0
  39. package/editors/vscode/snippets/mint.json +12 -0
  40. package/editors/vscode/snippets/shift.json +17 -0
  41. package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
  42. package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
  43. package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
  44. package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
  45. package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
  46. package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
  47. package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
  48. package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
  49. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
  50. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
  51. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
  52. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
  53. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
  54. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
  55. package/examples/game/.cluaupp/compile-cache/index.json +12 -0
  56. package/examples/game/.cluaupp/datamodel-profile.json +94 -0
  57. package/examples/game/.vscode/settings.json +12 -1
  58. package/examples/game/include/clpp/datatypes.clh +337 -373
  59. package/examples/game/include/clpp/generated/datamodel.clh +25 -0
  60. package/examples/game/include/clpp/generated/enums.clh +1 -1
  61. package/examples/game/include/clpp/generated/instances.clh +41135 -41064
  62. package/examples/game/include/clpp/libs/axiom.clh +1 -1
  63. package/examples/game/include/clpp/libs/math.clh +14 -0
  64. package/examples/game/include/clpp/libs/spring.clh +17 -0
  65. package/examples/game/include/clpp/libs/ward.clh +1 -0
  66. package/examples/game/include/clpp/roblox.clh +3 -4
  67. package/examples/game/libs/ArrayIndexer/init.luau +209 -0
  68. package/examples/game/libs/Axiom/init.luau +608 -0
  69. package/examples/game/libs/Bloom/init.luau +433 -0
  70. package/examples/game/libs/Coil/init.luau +215 -0
  71. package/examples/game/libs/Crest/init.luau +426 -0
  72. package/examples/game/libs/Echo/init.luau +417 -0
  73. package/examples/game/libs/Ember/init.luau +365 -0
  74. package/examples/game/libs/Flare/init.luau +717 -0
  75. package/examples/game/libs/Gleam/init.luau +729 -0
  76. package/examples/game/libs/Guide/init.luau +215 -0
  77. package/examples/game/libs/Helm/init.luau +377 -0
  78. package/examples/game/libs/Hive/init.luau +241 -0
  79. package/examples/game/libs/Keep/Client.luau +114 -0
  80. package/examples/game/libs/Keep/Data.luau +883 -0
  81. package/examples/game/libs/Keep/Engine.luau +211 -0
  82. package/examples/game/libs/Keep/Enum.luau +6 -0
  83. package/examples/game/libs/Keep/Enums.luau +10 -0
  84. package/examples/game/libs/Keep/Path.luau +236 -0
  85. package/examples/game/libs/Keep/Replicator.luau +298 -0
  86. package/examples/game/libs/Keep/Server.luau +251 -0
  87. package/examples/game/libs/Keep/Store.luau +652 -0
  88. package/examples/game/libs/Keep/Trade.luau +455 -0
  89. package/examples/game/libs/Keep/init.luau +205 -0
  90. package/examples/game/libs/Lens/init.luau +609 -0
  91. package/examples/game/libs/Mint/init.luau +279 -0
  92. package/examples/game/libs/Net/init.luau +156 -0
  93. package/examples/game/libs/Net/src/codec.luau +224 -0
  94. package/examples/game/libs/Occlude/init.luau +117 -0
  95. package/examples/game/libs/Pin/init.luau +309 -0
  96. package/examples/game/libs/Promise/LICENSE +21 -0
  97. package/examples/game/libs/Promise/_impl/LICENSE +21 -0
  98. package/examples/game/libs/Promise/_impl/init.lua +1991 -0
  99. package/examples/game/libs/Promise/init.lua +1990 -0
  100. package/examples/game/libs/Promise/init.luau +13 -0
  101. package/examples/game/libs/Promise/types.luau +46 -0
  102. package/examples/game/libs/Roster/init.luau +686 -0
  103. package/examples/game/libs/SOURCES.md +31 -0
  104. package/examples/game/libs/Shift/init.luau +238 -0
  105. package/examples/game/libs/Spark/init.luau +487 -0
  106. package/examples/game/libs/Stage/init.luau +178 -0
  107. package/examples/game/libs/Sweep/init.luau +259 -0
  108. package/examples/game/libs/Trace/init.luau +213 -0
  109. package/examples/game/libs/Ward/init.luau +211 -0
  110. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
  111. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
  112. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
  113. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
  114. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
  115. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
  116. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
  117. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
  118. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
  119. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
  120. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
  121. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
  122. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
  123. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
  124. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
  125. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
  126. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +26 -0
  127. package/examples/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  128. package/examples/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  129. package/examples/game/stylua.toml +9 -0
  130. package/generated/api/build-profile.js +115 -0
  131. package/generated/api/cache.js +44 -0
  132. package/generated/api/coverage.js +32 -0
  133. package/generated/api/diff.js +125 -0
  134. package/generated/api/generators/clpp-headers.js +353 -0
  135. package/generated/api/generators/docs-reference.js +7 -0
  136. package/generated/api/generators/lsp-index.js +81 -0
  137. package/generated/api/generators/luau-defs.js +94 -0
  138. package/generated/api/ide.js +76 -0
  139. package/generated/api/identifier.js +47 -0
  140. package/generated/api/index.js +324 -0
  141. package/generated/api/loader.js +57 -0
  142. package/generated/api/merge.js +88 -0
  143. package/generated/api/model.js +5 -0
  144. package/generated/api/normalize.js +231 -0
  145. package/generated/api/overrides-validate.js +58 -0
  146. package/generated/api/perf.js +12 -0
  147. package/generated/api/registry.js +136 -0
  148. package/generated/api/release.js +44 -0
  149. package/generated/api/resolver.js +250 -0
  150. package/generated/api/sources/aux-types-diff.js +75 -0
  151. package/generated/api/sources/client-tracker.js +11 -0
  152. package/generated/api/sources/creator-docs.js +42 -0
  153. package/generated/api/sources/luau-types.js +34 -0
  154. package/generated/api/sources/mini-dump.js +17 -0
  155. package/generated/api/sources/studio-api.js +8 -0
  156. package/generated/api/sources/studio-apiv2.js +11 -0
  157. package/generated/api/sources/studio-full-api.js +8 -0
  158. package/generated/api/studio-smoke.js +80 -0
  159. package/generated/api/type-parse.js +49 -0
  160. package/generated/api/understander.js +51 -0
  161. package/generated/api/validate.js +135 -0
  162. package/generated/api-cli.js +421 -0
  163. package/generated/cli.js +16 -5
  164. package/generated/clpp/contract.js +3 -3
  165. package/generated/clpp/format-luau.js +236 -0
  166. package/generated/clpp/index.js +13 -1
  167. package/generated/clpp/modules.js +227 -0
  168. package/generated/clpp/postprocess.js +86 -5
  169. package/generated/clpp/rewrite-janitor.js +145 -0
  170. package/generated/clpp/runner.js +14 -2
  171. package/generated/compile.js +82 -0
  172. package/generated/flare/parse.js +12 -1
  173. package/generated/intellisense.js +57 -1
  174. package/generated/native/index.js +217 -16
  175. package/generated/target/authority-check.js +136 -0
  176. package/generated/target/authority-graph.js +74 -0
  177. package/generated/target/build-cache.js +112 -0
  178. package/generated/target/capabilities.js +89 -0
  179. package/generated/target/capability-profile.js +30 -0
  180. package/generated/target/component-contracts.js +60 -0
  181. package/generated/target/context-check.js +160 -0
  182. package/generated/target/datamodel-check.js +170 -0
  183. package/generated/target/datamodel-generate.js +74 -0
  184. package/generated/target/datamodel.js +233 -0
  185. package/generated/target/diagnostics.js +63 -0
  186. package/generated/target/doctor.js +152 -0
  187. package/generated/target/flare-version.js +58 -0
  188. package/generated/target/get-service.js +69 -0
  189. package/generated/target/lifetime-check.js +47 -0
  190. package/generated/target/luau-stamp.js +39 -0
  191. package/generated/target/optimizer-advise.js +88 -0
  192. package/generated/target/optimizer-apply.js +44 -0
  193. package/generated/target/optimizer-soa.js +254 -0
  194. package/generated/target/parallel-check.js +136 -0
  195. package/generated/target/pgo.js +148 -0
  196. package/generated/target/project-docs.js +69 -0
  197. package/generated/target/project-graph.js +71 -0
  198. package/generated/target/roblox.js +63 -0
  199. package/generated/target/security-check.js +41 -0
  200. package/generated/target/source-map.js +25 -0
  201. package/generated/target/studio-bridge.js +112 -0
  202. package/generated/utils/project.js +178 -8
  203. package/generated/utils/rojo-mapper.js +11 -3
  204. package/include/clpp/datatypes.clh +337 -373
  205. package/include/clpp/generated/enums.clh +1 -1
  206. package/include/clpp/generated/instances.clh +41135 -41064
  207. package/include/clpp/libs/axiom.clh +1 -1
  208. package/include/clpp/libs/hive.clh +1 -0
  209. package/include/clpp/libs/keep.clh +2 -0
  210. package/include/clpp/libs/math.clh +14 -0
  211. package/include/clpp/libs/spring.clh +17 -0
  212. package/include/clpp/libs/ward.clh +1 -0
  213. package/include/clpp/roblox.clh +3 -4
  214. package/package.json +10 -3
  215. package/plugins/CluauppNav/Plugin.luau +207 -0
  216. package/plugins/CluauppNav/ProfileLogger.luau +27 -0
  217. package/plugins/CluauppNav/README.md +24 -0
  218. package/runtime/Axiom/init.luau +10 -7
  219. package/runtime/Coil/init.luau +8 -2
  220. package/runtime/Crest/init.luau +1 -0
  221. package/runtime/Flare/init.luau +2 -1
  222. package/runtime/Gleam/init.luau +15 -4
  223. package/runtime/Hive/init.luau +36 -14
  224. package/runtime/Pin/init.luau +5 -2
  225. package/runtime/Roster/init.luau +2 -0
  226. package/runtime/Spark/init.luau +3 -0
  227. package/runtime/Sweep/init.luau +2 -0
  228. package/runtime/Trace/init.luau +3 -0
  229. package/runtime/Ward/init.luau +38 -5
  230. package/scripts/postinstall-editor.js +17 -0
  231. package/skills/README.md +13 -0
  232. package/skills/clpp-hive-flare/SKILL.md +79 -0
  233. package/skills/clpp-language/SKILL.md +123 -0
  234. package/skills/clpp-language/compiler.md +89 -0
  235. package/skills/clpp-style/SKILL.md +95 -0
  236. package/src/api/build-profile.ts +138 -0
  237. package/src/api/cache.ts +45 -0
  238. package/src/api/coverage.ts +46 -0
  239. package/src/api/diff.ts +143 -0
  240. package/src/api/generators/clpp-headers.ts +377 -0
  241. package/src/api/generators/docs-reference.ts +11 -0
  242. package/src/api/generators/lsp-index.ts +106 -0
  243. package/src/api/generators/luau-defs.ts +98 -0
  244. package/src/api/ide.ts +87 -0
  245. package/src/api/identifier.ts +47 -0
  246. package/src/api/index.ts +269 -0
  247. package/src/api/loader.ts +60 -0
  248. package/src/api/merge.ts +126 -0
  249. package/src/api/model.ts +283 -0
  250. package/src/api/normalize.ts +257 -0
  251. package/src/api/overrides-validate.ts +58 -0
  252. package/src/api/perf.ts +15 -0
  253. package/src/api/registry.ts +162 -0
  254. package/src/api/release.ts +47 -0
  255. package/src/api/resolver.ts +255 -0
  256. package/src/api/sources/aux-types-diff.ts +81 -0
  257. package/src/api/sources/client-tracker.ts +10 -0
  258. package/src/api/sources/creator-docs.ts +37 -0
  259. package/src/api/sources/luau-types.ts +30 -0
  260. package/src/api/sources/mini-dump.ts +50 -0
  261. package/src/api/sources/studio-api.ts +7 -0
  262. package/src/api/sources/studio-apiv2.ts +10 -0
  263. package/src/api/sources/studio-full-api.ts +7 -0
  264. package/src/api/studio-smoke.ts +82 -0
  265. package/src/api/type-parse.ts +48 -0
  266. package/src/api/understander.ts +72 -0
  267. package/src/api/validate.ts +160 -0
  268. package/src/api-cli.ts +493 -0
  269. package/src/api.generated.js +37 -22
  270. package/src/cli.ts +21 -6
  271. package/src/clpp/contract.ts +34 -3
  272. package/src/clpp/format-luau.ts +262 -0
  273. package/src/clpp/index.ts +13 -2
  274. package/src/clpp/modules.ts +252 -0
  275. package/src/clpp/postprocess.ts +100 -5
  276. package/src/clpp/rewrite-janitor.ts +156 -0
  277. package/src/clpp/runner.ts +14 -2
  278. package/src/compile.ts +87 -0
  279. package/src/flare/parse.ts +14 -1
  280. package/src/flare/types.ts +2 -0
  281. package/src/intellisense.ts +58 -1
  282. package/src/native/index.ts +225 -16
  283. package/src/target/authority-check.ts +162 -0
  284. package/src/target/authority-graph.ts +80 -0
  285. package/src/target/build-cache.ts +129 -0
  286. package/src/target/capabilities.ts +115 -0
  287. package/src/target/capability-profile.ts +25 -0
  288. package/src/target/component-contracts.ts +64 -0
  289. package/src/target/context-check.ts +177 -0
  290. package/src/target/datamodel-check.ts +188 -0
  291. package/src/target/datamodel-generate.ts +78 -0
  292. package/src/target/datamodel.ts +261 -0
  293. package/src/target/diagnostics.ts +67 -0
  294. package/src/target/doctor.ts +171 -0
  295. package/src/target/flare-version.ts +61 -0
  296. package/src/target/get-service.ts +85 -0
  297. package/src/target/lifetime-check.ts +45 -0
  298. package/src/target/luau-stamp.ts +33 -0
  299. package/src/target/optimizer-advise.ts +93 -0
  300. package/src/target/optimizer-apply.ts +63 -0
  301. package/src/target/optimizer-soa.ts +270 -0
  302. package/src/target/parallel-check.ts +135 -0
  303. package/src/target/pgo.ts +157 -0
  304. package/src/target/project-docs.ts +68 -0
  305. package/src/target/project-graph.ts +75 -0
  306. package/src/target/roblox.ts +78 -0
  307. package/src/target/security-check.ts +40 -0
  308. package/src/target/source-map.ts +36 -0
  309. package/src/target/studio-bridge.ts +140 -0
  310. package/src/types.ts +14 -0
  311. package/src/utils/project.ts +183 -9
  312. package/src/utils/rojo-mapper.ts +12 -3
  313. package/stylua.toml +9 -0
  314. package/templates/game/.vscode/settings.json +7 -1
  315. package/templates/game/include/clpp/datatypes.clh +337 -373
  316. package/templates/game/include/clpp/generated/enums.clh +1 -1
  317. package/templates/game/include/clpp/generated/instances.clh +41135 -41064
  318. package/templates/game/include/clpp/libs/axiom.clh +1 -1
  319. package/templates/game/include/clpp/libs/ward.clh +1 -0
  320. package/templates/game/include/clpp/roblox.clh +3 -4
  321. package/templates/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  322. package/templates/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  323. package/templates/game/stylua.toml +9 -0
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Generate project documentation from DataModel + graph + Flare + advice.
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.generateProjectDocs = generateProjectDocs;
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const datamodel_js_1 = require("./datamodel.js");
13
+ const project_graph_js_1 = require("./project-graph.js");
14
+ const flare_version_js_1 = require("./flare-version.js");
15
+ const paths_js_1 = require("../clpp/paths.js");
16
+ const optimizer_advise_js_1 = require("./optimizer-advise.js");
17
+ function generateProjectDocs(projectRoot, rootDir = "src") {
18
+ const dm = (0, datamodel_js_1.buildDatamodelProfile)(projectRoot);
19
+ const graph = (0, project_graph_js_1.buildProjectGraph)(projectRoot, rootDir);
20
+ const flare = (0, flare_version_js_1.checkFlareVersions)(projectRoot, rootDir);
21
+ const srcDir = node_path_1.default.join(projectRoot, rootDir);
22
+ const files = node_fs_1.default.existsSync(srcDir) ? (0, paths_js_1.collectSources)(srcDir) : [];
23
+ const advice = [];
24
+ for (const file of files) {
25
+ const rel = node_path_1.default.relative(projectRoot, file).replace(/\\/g, "/");
26
+ for (const a of (0, optimizer_advise_js_1.adviseOptimizer)(node_fs_1.default.readFileSync(file, "utf8"), rel)) {
27
+ advice.push(`- **${a.target}** (${a.kind}): ${a.message}`);
28
+ }
29
+ }
30
+ const paths = dm
31
+ ? Object.keys(dm.byPath)
32
+ .filter((p) => p !== "DataModel")
33
+ .sort()
34
+ .map((p) => `- \`${p}\` — ${dm.byPath[p].className}`)
35
+ .join("\n")
36
+ : "_no default.project.json_";
37
+ const markdown = [
38
+ `# Cluaupp project docs`,
39
+ ``,
40
+ `Generated: ${new Date().toISOString()}`,
41
+ ``,
42
+ `## DataModel`,
43
+ ``,
44
+ paths,
45
+ ``,
46
+ `## Modules (${graph.nodes.length})`,
47
+ ``,
48
+ graph.nodes.map((n) => `- \`${n}\``).join("\n") || "_none_",
49
+ ``,
50
+ `## Dependencies`,
51
+ ``,
52
+ graph.edges.map((e) => `- \`${e.from}\` → \`${e.to}\``).join("\n") || "_none_",
53
+ ``,
54
+ graph.cycles.length ? `### Cycles\n\n${graph.cycles.map((c) => `- ${c.join(" → ")}`).join("\n")}\n` : "",
55
+ `## Flare contracts`,
56
+ ``,
57
+ flare.files.map((f) => `- \`${f.file}\` name=\`${f.name}\` version=${f.version ?? "unset"}`).join("\n") || "_none_",
58
+ ``,
59
+ `## Optimizer advice`,
60
+ ``,
61
+ advice.slice(0, 40).join("\n") || "_none_",
62
+ ``,
63
+ ].join("\n");
64
+ const outDir = node_path_1.default.join(projectRoot, ".cluaupp");
65
+ node_fs_1.default.mkdirSync(outDir, { recursive: true });
66
+ const outPath = node_path_1.default.join(outDir, "PROJECT.md");
67
+ node_fs_1.default.writeFileSync(outPath, markdown, "utf8");
68
+ return { outPath, markdown };
69
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildProjectGraph = buildProjectGraph;
7
+ /** Project include/import/require graph + circular dependency detection. */
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const modules_js_1 = require("../clpp/modules.js");
11
+ const paths_js_1 = require("../clpp/paths.js");
12
+ function findCycles(nodes, edges) {
13
+ const adj = new Map();
14
+ for (const n of nodes)
15
+ adj.set(n, []);
16
+ for (const e of edges) {
17
+ if (!adj.has(e.from))
18
+ adj.set(e.from, []);
19
+ adj.get(e.from).push(e.to);
20
+ }
21
+ const cycles = [];
22
+ const visiting = new Set();
23
+ const visited = new Set();
24
+ const stack = [];
25
+ function dfs(n) {
26
+ if (visiting.has(n)) {
27
+ const i = stack.indexOf(n);
28
+ if (i >= 0)
29
+ cycles.push(stack.slice(i).concat(n));
30
+ return;
31
+ }
32
+ if (visited.has(n))
33
+ return;
34
+ visiting.add(n);
35
+ stack.push(n);
36
+ for (const to of adj.get(n) || [])
37
+ dfs(to);
38
+ stack.pop();
39
+ visiting.delete(n);
40
+ visited.add(n);
41
+ }
42
+ for (const n of nodes)
43
+ dfs(n);
44
+ return cycles;
45
+ }
46
+ function buildProjectGraph(projectRoot, rootDir = "src") {
47
+ const srcDir = node_path_1.default.join(projectRoot, rootDir);
48
+ const files = node_fs_1.default.existsSync(srcDir) ? (0, paths_js_1.collectSources)(srcDir) : [];
49
+ const nodes = [];
50
+ const edges = [];
51
+ const byAbs = new Map();
52
+ for (const file of files) {
53
+ const rel = node_path_1.default.relative(projectRoot, file).replace(/\\/g, "/");
54
+ nodes.push(rel);
55
+ byAbs.set(node_path_1.default.resolve(file), rel);
56
+ }
57
+ for (const file of files) {
58
+ const rel = node_path_1.default.relative(projectRoot, file).replace(/\\/g, "/");
59
+ const source = node_fs_1.default.readFileSync(file, "utf8");
60
+ for (const mod of (0, modules_js_1.collectLanguageModulePaths)(source)) {
61
+ const resolved = (0, modules_js_1.resolveModuleFile)(mod, file, srcDir);
62
+ if (!resolved)
63
+ continue;
64
+ const hit = byAbs.get(node_path_1.default.resolve(resolved));
65
+ if (hit && hit !== rel) {
66
+ edges.push({ from: rel, to: hit });
67
+ }
68
+ }
69
+ }
70
+ return { nodes, edges, cycles: findCycles(nodes, edges) };
71
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FILE_TAG_TO_CONTEXT = void 0;
4
+ exports.runContextFromFileName = runContextFromFileName;
5
+ exports.defaultRobloxProject = defaultRobloxProject;
6
+ exports.resolveGetServiceType = resolveGetServiceType;
7
+ exports.isRegisteredService = isRegisteredService;
8
+ exports.targetProfileSummary = targetProfileSummary;
9
+ const model_js_1 = require("../api/model.js");
10
+ const build_profile_js_1 = require("../api/build-profile.js");
11
+ exports.FILE_TAG_TO_CONTEXT = {
12
+ ".server": "Server",
13
+ ".client": "Client",
14
+ ".plugin": "Plugin",
15
+ };
16
+ function runContextFromFileName(fileName) {
17
+ const lower = fileName.toLowerCase();
18
+ if (lower.includes(".server.")) {
19
+ return "Server";
20
+ }
21
+ if (lower.includes(".client.")) {
22
+ return "Client";
23
+ }
24
+ if (lower.includes(".plugin.")) {
25
+ return "Plugin";
26
+ }
27
+ return "Shared";
28
+ }
29
+ function defaultRobloxProject() {
30
+ return {
31
+ kind: "roblox",
32
+ libsFolderName: "CluauppLibs",
33
+ legacyLibsAlias: "ClppLibs",
34
+ };
35
+ }
36
+ /**
37
+ * Target-side GetService\<T\> — **Cluaupp Roblox Target feature**, not a CL++ language rule.
38
+ * CL++ only provides generic-call syntax (`GetService<Players>()`); Cluaupp maps T via the
39
+ * Canonical Registry, Context Safety, and headers under `#include <clpp/roblox.clh>`.
40
+ */
41
+ function resolveGetServiceType(typeName, profile) {
42
+ const p = profile || (0, build_profile_js_1.buildRobloxTargetProfile)({ skipValidate: true });
43
+ if (p.services[typeName]) {
44
+ return typeName;
45
+ }
46
+ if (p.classes[typeName]?.service || p.classes[typeName]?.creation.service) {
47
+ return typeName;
48
+ }
49
+ return null;
50
+ }
51
+ /** True when `name` is a registered Roblox service class. */
52
+ function isRegisteredService(name, profile) {
53
+ return resolveGetServiceType(name, profile) != null;
54
+ }
55
+ function targetProfileSummary() {
56
+ const profile = (0, build_profile_js_1.buildRobloxTargetProfile)({ skipValidate: true });
57
+ return {
58
+ schemaVersion: model_js_1.ROBLOX_TARGET_SCHEMA_VERSION,
59
+ target: "roblox",
60
+ classes: Object.keys(profile.classes).length,
61
+ services: Object.keys(profile.services).length,
62
+ };
63
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkSecurity = checkSecurity;
4
+ /** Static security patterns (CLUAU-SEC*) — not a runtime anti-cheat. */
5
+ const roblox_js_1 = require("./roblox.js");
6
+ const diagnostics_js_1 = require("./diagnostics.js");
7
+ const CLIENT_PATTERNS = [
8
+ { code: "CLUAU_SEC001", re: /\bCoins\s*=/, message: "Client appears to assign Coins — server must own currency" },
9
+ { code: "CLUAU_SEC002", re: /\bDamage\s*=\s*[^=]/, message: "Client appears to set Damage — prefer server authority" },
10
+ { code: "CLUAU_SEC003", re: /FireServer\s*\([^)]*Instance/, message: "Remote may accept unrestricted Instance from client" },
11
+ { code: "CLUAU_SEC004", re: /Inventory.*=.*FireServer|FireServer.*Inventory/, message: "Client-supplied inventory result smell" },
12
+ ];
13
+ const SERVER_PATTERNS = [
14
+ { code: "CLUAU_SEC010", re: /FireServer/, message: "Server calling FireServer is inverted authority" },
15
+ {
16
+ code: "CLUAU_SEC011",
17
+ re: /\.Position\b[^\n]*player|player[^\n]*\.Position/,
18
+ message: "Server may be trusting client Position — validate or ignore client transform",
19
+ },
20
+ ];
21
+ function checkSecurity(source, fileName) {
22
+ const ctx = (0, roblox_js_1.runContextFromFileName)(fileName);
23
+ const clean = (0, diagnostics_js_1.stripCommentsKeepStrings)(source);
24
+ const out = [];
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)
29
+ continue;
30
+ const { line, column } = (0, diagnostics_js_1.lineColAt)(clean, m.index);
31
+ out.push({
32
+ code: p.code,
33
+ message: p.message,
34
+ line,
35
+ column,
36
+ severity: "warning",
37
+ file: fileName,
38
+ });
39
+ }
40
+ return out;
41
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.writeSourceMap = writeSourceMap;
7
+ /** Minimal source map: CL++ path ↔ emitted Luau (1:1 file mapping for v1). */
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ function writeSourceMap(opts) {
11
+ const map = {
12
+ version: 1,
13
+ file: node_path_1.default.basename(opts.outLuauPath),
14
+ sourceRoot: opts.projectRoot.replace(/\\/g, "/"),
15
+ sources: [opts.sourceClppRel.replace(/\\/g, "/")],
16
+ mappings: "AAAA", // identity stub — refine when clpp emits VLQ maps
17
+ cluaupp: {
18
+ source: opts.sourceClppRel.replace(/\\/g, "/"),
19
+ generated: node_path_1.default.relative(opts.projectRoot, opts.outLuauPath).replace(/\\/g, "/"),
20
+ },
21
+ };
22
+ const mapPath = opts.outLuauPath + ".map.json";
23
+ node_fs_1.default.writeFileSync(mapPath, JSON.stringify(map, null, "\t") + "\n", "utf8");
24
+ return mapPath;
25
+ }
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Local HTTP bridge: Studio plugin ↔ IDE (VS Code / Cursor).
4
+ * Default port 3847. Studio POSTs open requests; IDE polls /events.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.BRIDGE_DEFAULT_PORT = void 0;
11
+ exports.startStudioBridge = startStudioBridge;
12
+ const node_http_1 = __importDefault(require("node:http"));
13
+ const node_fs_1 = __importDefault(require("node:fs"));
14
+ const node_path_1 = __importDefault(require("node:path"));
15
+ const node_events_1 = require("node:events");
16
+ exports.BRIDGE_DEFAULT_PORT = 3847;
17
+ function startStudioBridge(opts = {}) {
18
+ const port = opts.port ?? exports.BRIDGE_DEFAULT_PORT;
19
+ const bus = new node_events_1.EventEmitter();
20
+ const events = [];
21
+ let nextId = 1;
22
+ const push = (partial) => {
23
+ const ev = {
24
+ id: nextId++,
25
+ at: new Date().toISOString(),
26
+ ...partial,
27
+ };
28
+ events.push(ev);
29
+ if (events.length > 200)
30
+ events.shift();
31
+ bus.emit("event", ev);
32
+ opts.onEvent?.(ev);
33
+ return ev;
34
+ };
35
+ const server = node_http_1.default.createServer((req, res) => {
36
+ const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
37
+ res.setHeader("Access-Control-Allow-Origin", "*");
38
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
39
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
40
+ if (req.method === "OPTIONS") {
41
+ res.writeHead(204);
42
+ res.end();
43
+ return;
44
+ }
45
+ if (req.method === "GET" && url.pathname === "/health") {
46
+ res.writeHead(200, { "Content-Type": "application/json" });
47
+ res.end(JSON.stringify({ ok: true, service: "cluaupp-bridge", port }));
48
+ return;
49
+ }
50
+ if (req.method === "GET" && url.pathname === "/events") {
51
+ const since = Number(url.searchParams.get("since") || "0");
52
+ const batch = events.filter((e) => e.id > since);
53
+ res.writeHead(200, { "Content-Type": "application/json" });
54
+ res.end(JSON.stringify({ events: batch }));
55
+ return;
56
+ }
57
+ if (req.method === "POST" && url.pathname === "/open") {
58
+ let body = "";
59
+ req.on("data", (c) => {
60
+ body += c;
61
+ if (body.length > 1_000_000)
62
+ req.destroy();
63
+ });
64
+ req.on("end", () => {
65
+ try {
66
+ const data = JSON.parse(body || "{}");
67
+ const rel = (data.path || "").replace(/\\/g, "/");
68
+ if (opts.projectRoot && rel && !rel.includes("..")) {
69
+ const abs = node_path_1.default.resolve(opts.projectRoot, rel);
70
+ if (!abs.startsWith(node_path_1.default.resolve(opts.projectRoot))) {
71
+ res.writeHead(400);
72
+ res.end("bad path");
73
+ return;
74
+ }
75
+ if (!node_fs_1.default.existsSync(abs) && !rel.endsWith(".clpp") && !rel.endsWith(".clh")) {
76
+ /* still emit — file may be unsaved emit path */
77
+ }
78
+ }
79
+ const ev = push({
80
+ type: data.type || "open",
81
+ path: rel || undefined,
82
+ line: data.line,
83
+ instancePath: data.instancePath,
84
+ message: data.message,
85
+ });
86
+ res.writeHead(200, { "Content-Type": "application/json" });
87
+ res.end(JSON.stringify({ ok: true, id: ev.id }));
88
+ }
89
+ catch (err) {
90
+ res.writeHead(400);
91
+ res.end(String(err instanceof Error ? err.message : err));
92
+ }
93
+ });
94
+ return;
95
+ }
96
+ res.writeHead(404);
97
+ res.end("not found");
98
+ });
99
+ server.listen(port, "127.0.0.1");
100
+ return {
101
+ port,
102
+ close: () => {
103
+ server.close();
104
+ bus.removeAllListeners();
105
+ },
106
+ onEvent: (fn) => {
107
+ bus.on("event", fn);
108
+ return () => bus.off("event", fn);
109
+ },
110
+ getEventsSince: (id) => events.filter((e) => e.id > id),
111
+ };
112
+ }
@@ -13,6 +13,7 @@ exports.watch = watch;
13
13
  const node_fs_1 = __importDefault(require("node:fs"));
14
14
  const node_path_1 = __importDefault(require("node:path"));
15
15
  const package_info_js_1 = require("../package-info.js");
16
+ const postprocess_js_1 = require("../clpp/postprocess.js");
16
17
  const paths_js_1 = require("../clpp/paths.js");
17
18
  const index_js_1 = require("../flare/index.js");
18
19
  const index_js_2 = require("../native/index.js");
@@ -21,6 +22,16 @@ const process_orchestrator_js_1 = require("./process-orchestrator.js");
21
22
  const rojo_mapper_js_1 = require("./rojo-mapper.js");
22
23
  const transpile_js_1 = require("../transpile.js");
23
24
  const safe_paths_js_1 = require("./safe-paths.js");
25
+ const source_map_js_1 = require("../target/source-map.js");
26
+ const luau_stamp_js_1 = require("../target/luau-stamp.js");
27
+ const optimizer_soa_js_1 = require("../target/optimizer-soa.js");
28
+ const index_js_3 = require("../api/index.js");
29
+ const flare_version_js_1 = require("../target/flare-version.js");
30
+ const component_contracts_js_1 = require("../target/component-contracts.js");
31
+ const authority_check_js_1 = require("../target/authority-check.js");
32
+ const datamodel_js_1 = require("../target/datamodel.js");
33
+ const build_cache_js_1 = require("../target/build-cache.js");
34
+ const modules_js_1 = require("../clpp/modules.js");
24
35
  function readProjectConfig(file) {
25
36
  const raw = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
26
37
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
@@ -40,6 +51,12 @@ function readProjectConfig(file) {
40
51
  if (typeof data.architecture === "boolean") {
41
52
  parsed.architecture = data.architecture;
42
53
  }
54
+ if (data.rules && typeof data.rules === "object") {
55
+ parsed.rules = data.rules;
56
+ }
57
+ if (Array.isArray(data.components)) {
58
+ parsed.components = data.components;
59
+ }
43
60
  return parsed;
44
61
  }
45
62
  function loadConfig(root) {
@@ -356,41 +373,128 @@ function compileFlareJobs(root, config, srcDir) {
356
373
  }
357
374
  return { jobs, errors };
358
375
  }
359
- function compileProject(root, config, mapper) {
376
+ function configFingerprint(config) {
377
+ return JSON.stringify({
378
+ strict: config.strict === true,
379
+ architecture: config.architecture === true,
380
+ rootDir: config.rootDir,
381
+ outDir: config.outDir,
382
+ v: package_info_js_1.pkg.version,
383
+ });
384
+ }
385
+ function compileProject(root, config, mapper, options = {}) {
360
386
  const srcDir = node_path_1.default.join(root, config.rootDir);
361
387
  const schema = compileSchemaJobs(root, config, srcDir);
362
388
  const files = (0, paths_js_1.collectSources)(srcDir);
363
389
  const jobs = [...schema.jobs];
364
390
  const errors = [...schema.errors];
391
+ const incremental = options.incremental !== false;
392
+ const cfgKey = configFingerprint(config);
393
+ let cacheHits = 0;
365
394
  for (const file of files) {
366
395
  const source = node_fs_1.default.readFileSync(file, "utf8");
367
396
  const rel = posixRel(srcDir, file);
397
+ const sourceHash = (0, modules_js_1.fingerprintSourceWithDeps)(source, file, cfgKey, srcDir, build_cache_js_1.hashText);
368
398
  try {
399
+ if (incremental) {
400
+ const cached = (0, build_cache_js_1.readCachedJob)(root, rel, sourceHash);
401
+ if (cached) {
402
+ jobs.push({ rel, files: cached.files, stale: cached.stale || [] });
403
+ cacheHits++;
404
+ continue;
405
+ }
406
+ }
369
407
  const result = (0, transpile_js_1.transpileSource)(source, rel, compileOptions(root, config, file, rel), mapper);
370
408
  jobs.push({ rel, files: result.files, stale: result.stale || [] });
409
+ if (incremental) {
410
+ (0, build_cache_js_1.writeCachedJob)(root, {
411
+ rel,
412
+ sourceHash,
413
+ files: result.files,
414
+ stale: result.stale || [],
415
+ });
416
+ }
371
417
  }
372
418
  catch (err) {
373
419
  errors.push({ rel, prefixes: sourcePrefixes(rel), message: err.message });
374
420
  }
375
421
  }
422
+ if (cacheHits > 0) {
423
+ console.log(`cluaupp: incremental cache hit ${cacheHits}/${files.length}`);
424
+ }
376
425
  return { files, jobs, errors };
377
426
  }
378
- async function compileProjectAsync(root, config, mapper) {
427
+ async function compileProjectAsync(root, config, mapper, options = {}) {
379
428
  const srcDir = node_path_1.default.join(root, config.rootDir);
380
429
  const schema = compileSchemaJobs(root, config, srcDir);
381
430
  const files = (0, paths_js_1.collectSources)(srcDir);
382
431
  const jobs = [...schema.jobs];
383
432
  const errors = [...schema.errors];
384
- for (const file of files) {
433
+ const incremental = options.incremental !== false;
434
+ const cfgKey = configFingerprint(config);
435
+ const concurrency = options.jobs ?? (0, build_cache_js_1.defaultJobCount)();
436
+ let cacheHits = 0;
437
+ const compiled = await (0, build_cache_js_1.mapPool)(files, concurrency, async (file) => {
385
438
  const source = node_fs_1.default.readFileSync(file, "utf8");
386
439
  const rel = posixRel(srcDir, file);
440
+ const sourceHash = (0, modules_js_1.fingerprintSourceWithDeps)(source, file, cfgKey, srcDir, build_cache_js_1.hashText);
387
441
  try {
442
+ if (incremental) {
443
+ const cached = (0, build_cache_js_1.readCachedJob)(root, rel, sourceHash);
444
+ if (cached) {
445
+ return {
446
+ ok: true,
447
+ rel,
448
+ files: cached.files,
449
+ stale: cached.stale || [],
450
+ cached: true,
451
+ sourceHash,
452
+ };
453
+ }
454
+ }
388
455
  const result = await (0, transpile_js_1.transpileSourceAsync)(source, rel, compileOptions(root, config, file, rel), mapper);
389
- jobs.push({ rel, files: result.files, stale: result.stale || [] });
456
+ return {
457
+ ok: true,
458
+ rel,
459
+ files: result.files,
460
+ stale: result.stale || [],
461
+ cached: false,
462
+ sourceHash,
463
+ };
390
464
  }
391
465
  catch (err) {
392
- errors.push({ rel, prefixes: sourcePrefixes(rel), message: err.message });
466
+ return {
467
+ ok: false,
468
+ rel,
469
+ prefixes: sourcePrefixes(rel),
470
+ message: err.message,
471
+ };
393
472
  }
473
+ });
474
+ for (const item of compiled) {
475
+ if (item.ok) {
476
+ jobs.push({ rel: item.rel, files: item.files, stale: item.stale });
477
+ if (item.cached) {
478
+ cacheHits++;
479
+ }
480
+ else if (incremental) {
481
+ (0, build_cache_js_1.writeCachedJob)(root, {
482
+ rel: item.rel,
483
+ sourceHash: item.sourceHash,
484
+ files: item.files,
485
+ stale: item.stale,
486
+ });
487
+ }
488
+ }
489
+ else {
490
+ errors.push({ rel: item.rel, prefixes: item.prefixes, message: item.message });
491
+ }
492
+ }
493
+ if (cacheHits > 0) {
494
+ console.log(`cluaupp: incremental cache hit ${cacheHits}/${files.length} (jobs=${concurrency})`);
495
+ }
496
+ else if (files.length > 1 && concurrency > 1) {
497
+ console.log(`cluaupp: parallel compile jobs=${concurrency}`);
394
498
  }
395
499
  return { files, jobs, errors };
396
500
  }
@@ -424,11 +528,25 @@ function writeJobs(root, config, jobs, format) {
424
528
  if (!dest) {
425
529
  continue;
426
530
  }
427
- const changed = writeTextIfChanged(dest, artifact.contents);
531
+ let contents = artifact.contents;
532
+ if (/\.luau$/i.test(dest)) {
533
+ const srcFile = node_path_1.default.join(root, config.rootDir, job.rel);
534
+ const clppSource = node_fs_1.default.existsSync(srcFile) ? node_fs_1.default.readFileSync(srcFile, "utf8") : undefined;
535
+ contents = (0, luau_stamp_js_1.stampLuauFromClpp)((0, postprocess_js_1.rewriteClppEmit)(contents), job.rel, clppSource);
536
+ }
537
+ const changed = writeTextIfChanged(dest, contents);
428
538
  written.add(resolveKey(dest));
429
539
  if (changed) {
430
540
  console.log("cluaupp:", job.rel, "→", node_path_1.default.relative(root, dest));
431
541
  }
542
+ if (/\.luau$/i.test(dest)) {
543
+ const mapPath = (0, source_map_js_1.writeSourceMap)({
544
+ outLuauPath: dest,
545
+ sourceClppRel: job.rel,
546
+ projectRoot: root,
547
+ });
548
+ written.add(resolveKey(mapPath));
549
+ }
432
550
  if (format && /\.luau$/i.test(dest)) {
433
551
  process_orchestrator_js_1.ProcessOrchestrator.formatWithStyLuaSync(dest);
434
552
  }
@@ -468,6 +586,18 @@ function finishBuild(root, config, compiled, options) {
468
586
  }
469
587
  }
470
588
  const written = writeJobs(root, config, compiled.jobs, format);
589
+ try {
590
+ const soaPlans = (0, optimizer_soa_js_1.collectSoaPlansFromProject)(root, config.rootDir);
591
+ if (soaPlans.length) {
592
+ const files = (0, optimizer_soa_js_1.writeSoaArtifacts)(root, soaPlans, { useBuffer: false });
593
+ for (const f of files) {
594
+ console.log("cluaupp: SoA", node_path_1.default.relative(root, f));
595
+ }
596
+ }
597
+ }
598
+ catch (err) {
599
+ console.error("cluaupp: SoA emit failed", err.message);
600
+ }
471
601
  const failedPrefixes = compiled.errors.flatMap((err) => err.prefixes);
472
602
  pruneOut(root, config, written, failedPrefixes);
473
603
  try {
@@ -514,20 +644,49 @@ function prepareBuild(root, options) {
514
644
  }
515
645
  return { config, mapper: createMapper(root, config, options.rojo) };
516
646
  }
647
+ function enforceFrozen(root, config) {
648
+ const lock = (0, index_js_3.verifyLock)();
649
+ if (!lock.ok) {
650
+ throw new Error(`cluaupp build --frozen: API lock failed\n${lock.messages.join("\n")}`);
651
+ }
652
+ const flare = (0, flare_version_js_1.checkFlareVersions)(root, config.rootDir);
653
+ if (flare.conflicts.length) {
654
+ throw new Error(`cluaupp build --frozen: Flare version conflicts\n${flare.conflicts.map((c) => c.message).join("\n")}`);
655
+ }
656
+ const policy = (0, authority_check_js_1.loadPlatformPolicy)(root);
657
+ const components = config.components || policy.components || [];
658
+ if (components.length) {
659
+ const dm = (0, datamodel_js_1.buildDatamodelProfile)(root);
660
+ if (dm) {
661
+ const bad = (0, component_contracts_js_1.checkComponentContracts)(dm, components).filter((d) => d.severity === "error");
662
+ if (bad.length) {
663
+ throw new Error(`cluaupp build --frozen: component contracts\n${bad.map((b) => b.message).join("\n")}`);
664
+ }
665
+ }
666
+ }
667
+ }
517
668
  function build(root, options = {}) {
669
+ if (options.frozen) {
670
+ const config = loadConfig(root);
671
+ enforceFrozen(root, config);
672
+ }
518
673
  const prepared = prepareBuild(root, options);
519
674
  if (!prepared) {
520
675
  return { failed: 0, written: new Set() };
521
676
  }
522
- const compiled = compileProject(root, prepared.config, prepared.mapper);
677
+ const compiled = compileProject(root, prepared.config, prepared.mapper, options);
523
678
  return finishBuild(root, prepared.config, compiled, options);
524
679
  }
525
680
  async function buildAsync(root, options = {}) {
681
+ if (options.frozen) {
682
+ const config = loadConfig(root);
683
+ enforceFrozen(root, config);
684
+ }
526
685
  const prepared = prepareBuild(root, options);
527
686
  if (!prepared) {
528
687
  return { failed: 0, written: new Set() };
529
688
  }
530
- const compiled = await compileProjectAsync(root, prepared.config, prepared.mapper);
689
+ const compiled = await compileProjectAsync(root, prepared.config, prepared.mapper, options);
531
690
  return finishBuild(root, prepared.config, compiled, options);
532
691
  }
533
692
  async function init(dest) {
@@ -536,10 +695,21 @@ async function init(dest) {
536
695
  const include = node_path_1.default.join(__dirname, "..", "..", "include");
537
696
  copyDir(template, target);
538
697
  copyDir(include, node_path_1.default.join(target, "include"));
698
+ const skills = node_path_1.default.join(__dirname, "..", "..", "skills");
699
+ if (node_fs_1.default.existsSync(skills)) {
700
+ copyDir(skills, node_path_1.default.join(target, ".cursor", "skills"));
701
+ }
539
702
  copyRuntime(target);
540
703
  (0, intellisense_js_1.syncEditorSupport)(target);
704
+ try {
705
+ (0, intellisense_js_1.installEditorExtension)();
706
+ }
707
+ catch {
708
+ // editor homes may be missing in CI
709
+ }
541
710
  console.log("Cluaupp ready in", target);
542
711
  console.log(" clpp install (CL++ highlighting + IntelliSense)");
712
+ console.log(" cluaupp intellisense (schema .flare .hive .mint .bloom .helm .shift .axiom)");
543
713
  console.log(" rokit install");
544
714
  console.log(" cluaupp build");
545
715
  console.log(" rojo serve");