cluaupp 1.4.1 → 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.
- package/CHANGELOG.md +55 -0
- package/README.md +10 -5
- package/api/CHANGELOG.md +3 -0
- package/api/chat.js +74 -0
- package/api/fixtures/roblox/README.md +6 -0
- package/api/fixtures/roblox/aux/sample.d.luau +6 -0
- package/api/fixtures/roblox/mini/Mini-API-Dump.json +72 -0
- package/api/generated/bench-latest.json +39 -0
- package/api/generated/capability-profile.json +76 -0
- package/api/generated/lsp-index.json +1 -0
- package/api/generated/luau/classes.d.luau +11221 -0
- package/api/generated/luau/datatypes.d.luau +327 -0
- package/api/generated/luau/enums.d.luau +4918 -0
- package/api/generated/luau/globals.d.luau +12 -0
- package/api/manifests/roblox-target.manifest.json +22 -0
- package/api/normalized/roblox-target.profile.json +237461 -0
- package/api/overrides/classes.json +8 -0
- package/api/overrides/compatibility.json +9 -0
- package/api/overrides/datatypes.json +1579 -0
- package/api/overrides/enums.json +8 -0
- package/api/overrides/globals.json +8 -0
- package/api/overrides/type-mappings.json +9 -0
- package/api/roblox-api.lock.json +9 -0
- package/data/Mini-API-Dump.json +1 -0
- package/editors/vscode/README.md +19 -0
- package/editors/vscode/extension.js +222 -21
- package/editors/vscode/icons/axiom.svg +4 -0
- package/editors/vscode/icons/bloom.svg +5 -0
- package/editors/vscode/icons/flare.svg +5 -0
- package/editors/vscode/icons/helm.svg +4 -0
- package/editors/vscode/icons/hive.svg +5 -0
- package/editors/vscode/icons/mint.svg +4 -0
- package/editors/vscode/icons/shift.svg +6 -0
- package/editors/vscode/language-configuration-schema.json +24 -0
- package/editors/vscode/language-configuration.json +21 -0
- package/editors/vscode/package.json +220 -6
- package/editors/vscode/snippets/axiom.json +12 -0
- package/editors/vscode/snippets/bloom.json +12 -0
- package/editors/vscode/snippets/flare.json +27 -0
- package/editors/vscode/snippets/helm.json +12 -0
- package/editors/vscode/snippets/hive.json +12 -0
- package/editors/vscode/snippets/mint.json +12 -0
- package/editors/vscode/snippets/shift.json +17 -0
- package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
- package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
- package/editors/vscode/syntaxes/flare.tmLanguage.json +75 -0
- package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
- package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
- package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
- package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
- package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
- package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
- package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
- package/examples/game/.cluaupp/compile-cache/index.json +12 -0
- package/examples/game/.cluaupp/datamodel-profile.json +94 -0
- package/examples/game/.vscode/extensions.json +3 -1
- package/examples/game/.vscode/settings.json +13 -1
- package/examples/game/include/clpp/datatypes.clh +337 -373
- package/examples/game/include/clpp/generated/datamodel.clh +25 -0
- package/examples/game/include/clpp/generated/enums.clh +1 -1
- package/examples/game/include/clpp/generated/instances.clh +41135 -41064
- package/examples/game/include/clpp/libs/axiom.clh +1 -1
- package/examples/game/include/clpp/libs/math.clh +14 -0
- package/examples/game/include/clpp/libs/roster.clh +6 -0
- package/examples/game/include/clpp/libs/spring.clh +17 -0
- package/examples/game/include/clpp/libs/ward.clh +1 -0
- package/examples/game/include/clpp/roblox.clh +3 -4
- package/examples/game/libs/ArrayIndexer/init.luau +209 -0
- package/examples/game/libs/Axiom/init.luau +608 -0
- package/examples/game/libs/Bloom/init.luau +433 -0
- package/examples/game/libs/Coil/init.luau +215 -0
- package/examples/game/libs/Crest/init.luau +426 -0
- package/examples/game/libs/Echo/init.luau +417 -0
- package/examples/game/libs/Ember/init.luau +365 -0
- package/examples/game/libs/Flare/init.luau +717 -0
- package/examples/game/libs/Gleam/init.luau +729 -0
- package/examples/game/libs/Guide/init.luau +215 -0
- package/examples/game/libs/Helm/init.luau +377 -0
- package/examples/game/libs/Hive/init.luau +241 -0
- package/examples/game/libs/Keep/Client.luau +114 -0
- package/examples/game/libs/Keep/Data.luau +883 -0
- package/examples/game/libs/Keep/Engine.luau +211 -0
- package/examples/game/libs/Keep/Enum.luau +6 -0
- package/examples/game/libs/Keep/Enums.luau +10 -0
- package/examples/game/libs/Keep/Path.luau +236 -0
- package/examples/game/libs/Keep/Replicator.luau +298 -0
- package/examples/game/libs/Keep/Server.luau +251 -0
- package/examples/game/libs/Keep/Store.luau +652 -0
- package/examples/game/libs/Keep/Trade.luau +455 -0
- package/examples/game/libs/Keep/init.luau +205 -0
- package/examples/game/libs/Lens/init.luau +609 -0
- package/examples/game/libs/Mint/init.luau +279 -0
- package/examples/game/libs/Net/init.luau +156 -0
- package/examples/game/libs/Net/src/codec.luau +224 -0
- package/examples/game/libs/Occlude/init.luau +117 -0
- package/examples/game/libs/Pin/init.luau +309 -0
- package/examples/game/libs/Promise/LICENSE +21 -0
- package/examples/game/libs/Promise/_impl/LICENSE +21 -0
- package/examples/game/libs/Promise/_impl/init.lua +1991 -0
- package/examples/game/libs/Promise/init.lua +1990 -0
- package/examples/game/libs/Promise/init.luau +13 -0
- package/examples/game/libs/Promise/types.luau +46 -0
- package/examples/game/libs/Roster/init.luau +686 -0
- package/examples/game/libs/SOURCES.md +31 -0
- package/examples/game/libs/Shift/init.luau +238 -0
- package/examples/game/libs/Spark/init.luau +487 -0
- package/examples/game/libs/Stage/init.luau +178 -0
- package/examples/game/libs/Sweep/init.luau +259 -0
- package/examples/game/libs/Trace/init.luau +213 -0
- package/examples/game/libs/Ward/init.luau +211 -0
- package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
- package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
- package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
- package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
- package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
- package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
- package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
- package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
- package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
- package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
- package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +26 -0
- package/examples/game/src/ReplicatedStorage/Shared/Net/Net.flare +5 -0
- package/examples/game/src/ServerScriptService/Boot/DataBoot.server.clpp +2 -2
- package/examples/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
- package/examples/game/stylua.toml +9 -0
- package/generated/api/build-profile.js +115 -0
- package/generated/api/cache.js +44 -0
- package/generated/api/coverage.js +32 -0
- package/generated/api/diff.js +125 -0
- package/generated/api/generators/clpp-headers.js +353 -0
- package/generated/api/generators/docs-reference.js +7 -0
- package/generated/api/generators/lsp-index.js +81 -0
- package/generated/api/generators/luau-defs.js +94 -0
- package/generated/api/ide.js +76 -0
- package/generated/api/identifier.js +47 -0
- package/generated/api/index.js +324 -0
- package/generated/api/loader.js +57 -0
- package/generated/api/merge.js +88 -0
- package/generated/api/model.js +5 -0
- package/generated/api/normalize.js +231 -0
- package/generated/api/overrides-validate.js +58 -0
- package/generated/api/perf.js +12 -0
- package/generated/api/registry.js +136 -0
- package/generated/api/release.js +44 -0
- package/generated/api/resolver.js +250 -0
- package/generated/api/sources/aux-types-diff.js +75 -0
- package/generated/api/sources/client-tracker.js +11 -0
- package/generated/api/sources/creator-docs.js +42 -0
- package/generated/api/sources/luau-types.js +34 -0
- package/generated/api/sources/mini-dump.js +17 -0
- package/generated/api/sources/studio-api.js +8 -0
- package/generated/api/sources/studio-apiv2.js +11 -0
- package/generated/api/sources/studio-full-api.js +8 -0
- package/generated/api/studio-smoke.js +80 -0
- package/generated/api/type-parse.js +49 -0
- package/generated/api/understander.js +51 -0
- package/generated/api/validate.js +135 -0
- package/generated/api-cli.js +421 -0
- package/generated/cli.js +17 -6
- package/generated/clpp/contract.js +3 -3
- package/generated/clpp/format-luau.js +236 -0
- package/generated/clpp/index.js +13 -1
- package/generated/clpp/modules.js +227 -0
- package/generated/clpp/postprocess.js +86 -5
- package/generated/clpp/rewrite-janitor.js +145 -0
- package/generated/clpp/runner.js +14 -2
- package/generated/compile.js +82 -0
- package/generated/flare/index.js +15 -3
- package/generated/flare/language.js +561 -0
- package/generated/flare/parse.js +19 -7
- package/generated/intellisense.js +76 -2
- package/generated/lsp.js +118 -7
- package/generated/native/index.js +217 -16
- package/generated/target/authority-check.js +136 -0
- package/generated/target/authority-graph.js +74 -0
- package/generated/target/build-cache.js +112 -0
- package/generated/target/capabilities.js +89 -0
- package/generated/target/capability-profile.js +30 -0
- package/generated/target/component-contracts.js +60 -0
- package/generated/target/context-check.js +160 -0
- package/generated/target/datamodel-check.js +170 -0
- package/generated/target/datamodel-generate.js +74 -0
- package/generated/target/datamodel.js +233 -0
- package/generated/target/diagnostics.js +63 -0
- package/generated/target/doctor.js +152 -0
- package/generated/target/flare-version.js +58 -0
- package/generated/target/get-service.js +69 -0
- package/generated/target/lifetime-check.js +47 -0
- package/generated/target/luau-stamp.js +39 -0
- package/generated/target/optimizer-advise.js +88 -0
- package/generated/target/optimizer-apply.js +44 -0
- package/generated/target/optimizer-soa.js +254 -0
- package/generated/target/parallel-check.js +136 -0
- package/generated/target/pgo.js +148 -0
- package/generated/target/project-docs.js +69 -0
- package/generated/target/project-graph.js +71 -0
- package/generated/target/roblox.js +63 -0
- package/generated/target/security-check.js +41 -0
- package/generated/target/source-map.js +25 -0
- package/generated/target/studio-bridge.js +112 -0
- package/generated/utils/project.js +178 -8
- package/generated/utils/rojo-mapper.js +11 -3
- package/include/clpp/datatypes.clh +337 -373
- package/include/clpp/generated/enums.clh +1 -1
- package/include/clpp/generated/instances.clh +41135 -41064
- package/include/clpp/libs/axiom.clh +1 -1
- package/include/clpp/libs/hive.clh +1 -0
- package/include/clpp/libs/keep.clh +2 -0
- package/include/clpp/libs/math.clh +14 -0
- package/include/clpp/libs/roster.clh +6 -0
- package/include/clpp/libs/spring.clh +17 -0
- package/include/clpp/libs/ward.clh +1 -0
- package/include/clpp/roblox.clh +3 -4
- package/package.json +10 -3
- package/plugins/CluauppNav/Plugin.luau +207 -0
- package/plugins/CluauppNav/ProfileLogger.luau +27 -0
- package/plugins/CluauppNav/README.md +24 -0
- package/runtime/Axiom/init.luau +10 -7
- package/runtime/Coil/init.luau +8 -2
- package/runtime/Crest/init.luau +1 -0
- package/runtime/Flare/init.luau +2 -1
- package/runtime/Gleam/init.luau +15 -4
- package/runtime/Hive/init.luau +36 -14
- package/runtime/Pin/init.luau +5 -2
- package/runtime/Roster/init.luau +8 -0
- package/runtime/Spark/init.luau +3 -0
- package/runtime/Sweep/init.luau +2 -0
- package/runtime/Trace/init.luau +3 -0
- package/runtime/Ward/init.luau +38 -5
- package/scripts/postinstall-editor.js +17 -0
- package/skills/README.md +13 -0
- package/skills/clpp-hive-flare/SKILL.md +79 -0
- package/skills/clpp-language/SKILL.md +123 -0
- package/skills/clpp-language/compiler.md +89 -0
- package/skills/clpp-style/SKILL.md +95 -0
- package/src/api/build-profile.ts +138 -0
- package/src/api/cache.ts +45 -0
- package/src/api/coverage.ts +46 -0
- package/src/api/diff.ts +143 -0
- package/src/api/generators/clpp-headers.ts +377 -0
- package/src/api/generators/docs-reference.ts +11 -0
- package/src/api/generators/lsp-index.ts +106 -0
- package/src/api/generators/luau-defs.ts +98 -0
- package/src/api/ide.ts +87 -0
- package/src/api/identifier.ts +47 -0
- package/src/api/index.ts +269 -0
- package/src/api/loader.ts +60 -0
- package/src/api/merge.ts +126 -0
- package/src/api/model.ts +283 -0
- package/src/api/normalize.ts +257 -0
- package/src/api/overrides-validate.ts +58 -0
- package/src/api/perf.ts +15 -0
- package/src/api/registry.ts +162 -0
- package/src/api/release.ts +47 -0
- package/src/api/resolver.ts +255 -0
- package/src/api/sources/aux-types-diff.ts +81 -0
- package/src/api/sources/client-tracker.ts +10 -0
- package/src/api/sources/creator-docs.ts +37 -0
- package/src/api/sources/luau-types.ts +30 -0
- package/src/api/sources/mini-dump.ts +50 -0
- package/src/api/sources/studio-api.ts +7 -0
- package/src/api/sources/studio-apiv2.ts +10 -0
- package/src/api/sources/studio-full-api.ts +7 -0
- package/src/api/studio-smoke.ts +82 -0
- package/src/api/type-parse.ts +48 -0
- package/src/api/understander.ts +72 -0
- package/src/api/validate.ts +160 -0
- package/src/api-cli.ts +493 -0
- package/src/api.generated.js +37 -22
- package/src/cli.ts +22 -7
- package/src/clpp/contract.ts +34 -3
- package/src/clpp/format-luau.ts +262 -0
- package/src/clpp/index.ts +13 -2
- package/src/clpp/modules.ts +252 -0
- package/src/clpp/postprocess.ts +100 -5
- package/src/clpp/rewrite-janitor.ts +156 -0
- package/src/clpp/runner.ts +14 -2
- package/src/compile.ts +87 -0
- package/src/flare/index.ts +20 -1
- package/src/flare/language.ts +708 -0
- package/src/flare/parse.ts +20 -7
- package/src/flare/types.ts +2 -0
- package/src/intellisense.ts +76 -2
- package/src/lsp.ts +151 -8
- package/src/native/index.ts +225 -16
- package/src/target/authority-check.ts +162 -0
- package/src/target/authority-graph.ts +80 -0
- package/src/target/build-cache.ts +129 -0
- package/src/target/capabilities.ts +115 -0
- package/src/target/capability-profile.ts +25 -0
- package/src/target/component-contracts.ts +64 -0
- package/src/target/context-check.ts +177 -0
- package/src/target/datamodel-check.ts +188 -0
- package/src/target/datamodel-generate.ts +78 -0
- package/src/target/datamodel.ts +261 -0
- package/src/target/diagnostics.ts +67 -0
- package/src/target/doctor.ts +171 -0
- package/src/target/flare-version.ts +61 -0
- package/src/target/get-service.ts +85 -0
- package/src/target/lifetime-check.ts +45 -0
- package/src/target/luau-stamp.ts +33 -0
- package/src/target/optimizer-advise.ts +93 -0
- package/src/target/optimizer-apply.ts +63 -0
- package/src/target/optimizer-soa.ts +270 -0
- package/src/target/parallel-check.ts +135 -0
- package/src/target/pgo.ts +157 -0
- package/src/target/project-docs.ts +68 -0
- package/src/target/project-graph.ts +75 -0
- package/src/target/roblox.ts +78 -0
- package/src/target/security-check.ts +40 -0
- package/src/target/source-map.ts +36 -0
- package/src/target/studio-bridge.ts +140 -0
- package/src/types.ts +14 -0
- package/src/utils/project.ts +183 -9
- package/src/utils/rojo-mapper.ts +12 -3
- package/stylua.toml +9 -0
- package/templates/game/.vscode/extensions.json +3 -1
- package/templates/game/.vscode/settings.json +8 -1
- package/templates/game/include/clpp/datatypes.clh +337 -373
- package/templates/game/include/clpp/generated/enums.clh +1 -1
- package/templates/game/include/clpp/generated/instances.clh +41135 -41064
- package/templates/game/include/clpp/libs/axiom.clh +1 -1
- package/templates/game/include/clpp/libs/roster.clh +6 -0
- package/templates/game/include/clpp/libs/ward.clh +1 -0
- package/templates/game/include/clpp/roblox.clh +3 -4
- package/templates/game/src/ReplicatedStorage/Shared/Net/Net.flare +5 -0
- package/templates/game/src/ServerScriptService/Boot/DataBoot.server.clpp +2 -2
- package/templates/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
- package/templates/game/stylua.toml +9 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateProfile = validateProfile;
|
|
4
|
+
exports.assertValid = assertValid;
|
|
5
|
+
function validateProfile(profile) {
|
|
6
|
+
const issues = [];
|
|
7
|
+
const classNames = new Set(Object.keys(profile.classes));
|
|
8
|
+
const enumNames = new Set(Object.keys(profile.enums));
|
|
9
|
+
const datatypeNames = new Set(Object.keys(profile.datatypes));
|
|
10
|
+
for (const cls of Object.values(profile.classes)) {
|
|
11
|
+
if (cls.superclass && !classNames.has(cls.superclass)) {
|
|
12
|
+
issues.push({
|
|
13
|
+
severity: "warning",
|
|
14
|
+
code: "ORPHAN_SUPERCLASS",
|
|
15
|
+
message: `Class ${cls.name} references missing superclass ${cls.superclass}`,
|
|
16
|
+
symbol: cls.name,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
detectCycle(cls, profile.classes, issues);
|
|
20
|
+
for (const prop of cls.properties) {
|
|
21
|
+
checkTypeRefs(prop.valueType, `property ${cls.name}.${prop.name}`, classNames, enumNames, datatypeNames, issues);
|
|
22
|
+
}
|
|
23
|
+
for (const method of cls.methods) {
|
|
24
|
+
for (const p of method.parameters) {
|
|
25
|
+
checkTypeRefs(p.type, `method ${cls.name}.${method.name}`, classNames, enumNames, datatypeNames, issues);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const seenEnums = new Set();
|
|
30
|
+
for (const e of Object.values(profile.enums)) {
|
|
31
|
+
if (seenEnums.has(e.name)) {
|
|
32
|
+
issues.push({
|
|
33
|
+
severity: "error",
|
|
34
|
+
code: "DUPLICATE_ENUM",
|
|
35
|
+
message: `Duplicate enum ${e.name}`,
|
|
36
|
+
symbol: e.name,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
seenEnums.add(e.name);
|
|
40
|
+
const itemNames = new Set();
|
|
41
|
+
for (const item of e.items) {
|
|
42
|
+
if (itemNames.has(item.name)) {
|
|
43
|
+
issues.push({
|
|
44
|
+
severity: "warning",
|
|
45
|
+
code: "DUPLICATE_ENUM_ITEM",
|
|
46
|
+
message: `Duplicate enum item ${e.name}.${item.name}`,
|
|
47
|
+
symbol: `${e.name}.${item.name}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
itemNames.add(item.name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const u of profile.unsupported) {
|
|
54
|
+
if (u.severity === "error") {
|
|
55
|
+
issues.push({
|
|
56
|
+
severity: "error",
|
|
57
|
+
code: "UNSUPPORTED",
|
|
58
|
+
message: u.reason,
|
|
59
|
+
symbol: u.symbol,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return issues;
|
|
64
|
+
}
|
|
65
|
+
function detectCycle(cls, classes, issues) {
|
|
66
|
+
const seen = new Set();
|
|
67
|
+
let current = cls.name;
|
|
68
|
+
while (current) {
|
|
69
|
+
if (seen.has(current)) {
|
|
70
|
+
issues.push({
|
|
71
|
+
severity: "error",
|
|
72
|
+
code: "INHERITANCE_CYCLE",
|
|
73
|
+
message: `Inheritance cycle involving ${cls.name}`,
|
|
74
|
+
symbol: cls.name,
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
seen.add(current);
|
|
79
|
+
const nextCls = classes[current];
|
|
80
|
+
current = nextCls?.superclass || null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function checkTypeRefs(type, context, classes, enums, datatypes, issues) {
|
|
84
|
+
switch (type.kind) {
|
|
85
|
+
case "Class":
|
|
86
|
+
if (!classes.has(type.name) && !datatypes.has(type.name)) {
|
|
87
|
+
issues.push({
|
|
88
|
+
severity: "warning",
|
|
89
|
+
code: "UNRESOLVED_CLASS",
|
|
90
|
+
message: `Unresolved class type ${type.name} in ${context}`,
|
|
91
|
+
symbol: type.name,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
case "Enum":
|
|
96
|
+
if (!enums.has(type.name)) {
|
|
97
|
+
issues.push({
|
|
98
|
+
severity: "warning",
|
|
99
|
+
code: "UNRESOLVED_ENUM",
|
|
100
|
+
message: `Unresolved enum ${type.name} in ${context}`,
|
|
101
|
+
symbol: type.name,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
case "Datatype":
|
|
106
|
+
if (!datatypes.has(type.name) && !classes.has(type.name)) {
|
|
107
|
+
issues.push({
|
|
108
|
+
severity: "warning",
|
|
109
|
+
code: "UNRESOLVED_DATATYPE",
|
|
110
|
+
message: `Unresolved datatype ${type.name} in ${context}`,
|
|
111
|
+
symbol: type.name,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case "Optional":
|
|
116
|
+
checkTypeRefs(type.inner, context, classes, enums, datatypes, issues);
|
|
117
|
+
break;
|
|
118
|
+
case "Array":
|
|
119
|
+
checkTypeRefs(type.element, context, classes, enums, datatypes, issues);
|
|
120
|
+
break;
|
|
121
|
+
case "Dictionary":
|
|
122
|
+
case "Map":
|
|
123
|
+
checkTypeRefs(type.key, context, classes, enums, datatypes, issues);
|
|
124
|
+
checkTypeRefs(type.value, context, classes, enums, datatypes, issues);
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function assertValid(profile) {
|
|
131
|
+
const errors = validateProfile(profile).filter((i) => i.severity === "error");
|
|
132
|
+
if (errors.length) {
|
|
133
|
+
throw new Error(`RobloxTargetProfile invalid:\n${errors.map((e) => `- ${e.code}: ${e.message}`).join("\n")}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,421 @@
|
|
|
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.registerApiCommands = registerApiCommands;
|
|
7
|
+
exports.registerTargetCommands = registerTargetCommands;
|
|
8
|
+
exports.registerPlatformCommands = registerPlatformCommands;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const index_js_1 = require("./api/index.js");
|
|
11
|
+
const package_info_js_1 = require("./package-info.js");
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const paths_js_1 = require("./clpp/paths.js");
|
|
14
|
+
const node_child_process_1 = require("node:child_process");
|
|
15
|
+
const optimizer_apply_js_1 = require("./target/optimizer-apply.js");
|
|
16
|
+
const pgo_js_1 = require("./target/pgo.js");
|
|
17
|
+
const project_docs_js_1 = require("./target/project-docs.js");
|
|
18
|
+
const studio_bridge_js_1 = require("./target/studio-bridge.js");
|
|
19
|
+
const optimizer_soa_js_1 = require("./target/optimizer-soa.js");
|
|
20
|
+
function registerApiCommands(program) {
|
|
21
|
+
const api = program.command("api").description("Roblox API registry (Cluaupp target)");
|
|
22
|
+
api
|
|
23
|
+
.command("update")
|
|
24
|
+
.description("Rebuild profile from dump + overrides (alias of generate)")
|
|
25
|
+
.option("--dump <path>", "Mini-API-Dump.json path")
|
|
26
|
+
.action((opts) => {
|
|
27
|
+
runGenerate(opts.dump);
|
|
28
|
+
});
|
|
29
|
+
api
|
|
30
|
+
.command("generate")
|
|
31
|
+
.description("Build RobloxTargetProfile and regenerate CL++ / Luau projections")
|
|
32
|
+
.option("--dump <path>", "Mini-API-Dump.json path")
|
|
33
|
+
.option("--skip-headers", "Skip CL++ header generation")
|
|
34
|
+
.option("--skip-luau", "Skip .d.luau generation")
|
|
35
|
+
.option("--docs", "No-op retained for CLI compat (Creator Docs are not mirrored)")
|
|
36
|
+
.action((opts) => {
|
|
37
|
+
runGenerate(opts.dump, opts.skipHeaders, opts.skipLuau, true);
|
|
38
|
+
});
|
|
39
|
+
api
|
|
40
|
+
.command("verify")
|
|
41
|
+
.description("Verify roblox-api.lock.json against current sources")
|
|
42
|
+
.action(() => {
|
|
43
|
+
const result = (0, index_js_1.verifyLock)();
|
|
44
|
+
if (!result.ok) {
|
|
45
|
+
console.error("cluaupp api verify: FAILED");
|
|
46
|
+
for (const m of result.messages) {
|
|
47
|
+
console.error(" -", m);
|
|
48
|
+
}
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
console.log("cluaupp api verify: OK");
|
|
52
|
+
});
|
|
53
|
+
api
|
|
54
|
+
.command("diff")
|
|
55
|
+
.description("Diff current profile against a snapshot")
|
|
56
|
+
.argument("<snapshot>", "path to previous profile JSON")
|
|
57
|
+
.action((snapshot) => {
|
|
58
|
+
const entries = (0, index_js_1.apiDiffAgainstSnapshot)(node_path_1.default.resolve(snapshot));
|
|
59
|
+
console.log(JSON.stringify(entries, null, "\t"));
|
|
60
|
+
console.log(`cluaupp api diff: ${entries.length} change(s)`);
|
|
61
|
+
});
|
|
62
|
+
api
|
|
63
|
+
.command("inspect")
|
|
64
|
+
.description("Inspect a class, enum, datatype, or member")
|
|
65
|
+
.argument("<symbol>", "e.g. Players, Players.PlayerAdded, Vector3")
|
|
66
|
+
.action((symbol) => {
|
|
67
|
+
console.log(JSON.stringify((0, index_js_1.inspectSymbol)(symbol), null, "\t"));
|
|
68
|
+
});
|
|
69
|
+
api
|
|
70
|
+
.command("search")
|
|
71
|
+
.description("Search registry symbols")
|
|
72
|
+
.argument("<query>", "substring query")
|
|
73
|
+
.action((query) => {
|
|
74
|
+
const profile = (0, index_js_1.buildRobloxTargetProfile)({ skipValidate: true });
|
|
75
|
+
console.log(JSON.stringify((0, index_js_1.searchRegistry)((0, index_js_1.buildRegistry)(profile), query), null, "\t"));
|
|
76
|
+
});
|
|
77
|
+
api
|
|
78
|
+
.command("coverage")
|
|
79
|
+
.description("Report API surface coverage and UnsupportedRepresentation gaps")
|
|
80
|
+
.action(() => {
|
|
81
|
+
console.log(JSON.stringify((0, index_js_1.apiCoverage)(), null, "\t"));
|
|
82
|
+
});
|
|
83
|
+
api
|
|
84
|
+
.command("snapshot")
|
|
85
|
+
.description("Write api/snapshots/latest.profile.json")
|
|
86
|
+
.option("-o, --output <path>", "output path")
|
|
87
|
+
.action((opts) => {
|
|
88
|
+
const p = (0, index_js_1.writeSnapshot)(opts.output);
|
|
89
|
+
console.log("cluaupp api snapshot:", p);
|
|
90
|
+
});
|
|
91
|
+
api
|
|
92
|
+
.command("validate")
|
|
93
|
+
.description("Validate current RobloxTargetProfile")
|
|
94
|
+
.action(() => {
|
|
95
|
+
const issues = (0, index_js_1.validateCurrent)();
|
|
96
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
97
|
+
console.log(JSON.stringify(issues, null, "\t"));
|
|
98
|
+
if (errors.length) {
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
api
|
|
103
|
+
.command("analyze-luau")
|
|
104
|
+
.description("Run luau-analyze on generated .d.luau if available")
|
|
105
|
+
.action(() => {
|
|
106
|
+
const results = (0, index_js_1.analyzeLuauOutput)();
|
|
107
|
+
console.log(JSON.stringify(results, null, "\t"));
|
|
108
|
+
});
|
|
109
|
+
api
|
|
110
|
+
.command("aux-diff")
|
|
111
|
+
.description("Coverage cross-check vs local @rbxts/types or LuauTypes (not on compile path)")
|
|
112
|
+
.argument("<path>", "file or directory of auxiliary types")
|
|
113
|
+
.action((auxPath) => {
|
|
114
|
+
const profile = (0, index_js_1.buildRobloxTargetProfile)({ skipValidate: true });
|
|
115
|
+
const names = [
|
|
116
|
+
...Object.keys(profile.classes),
|
|
117
|
+
...Object.keys(profile.enums),
|
|
118
|
+
...Object.keys(profile.datatypes),
|
|
119
|
+
];
|
|
120
|
+
const report = (0, index_js_1.diffAgainstAuxTypes)(names, node_path_1.default.resolve(auxPath));
|
|
121
|
+
console.log(JSON.stringify({
|
|
122
|
+
source: report.source,
|
|
123
|
+
auxSymbols: report.auxSymbols,
|
|
124
|
+
registrySymbols: report.registrySymbols,
|
|
125
|
+
onlyInAuxCount: report.onlyInAux.length,
|
|
126
|
+
onlyInRegistryCount: report.onlyInRegistry.length,
|
|
127
|
+
onlyInAuxSample: report.onlyInAux.slice(0, 40),
|
|
128
|
+
onlyInRegistrySample: report.onlyInRegistry.slice(0, 40),
|
|
129
|
+
}, null, "\t"));
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function registerTargetCommands(program) {
|
|
133
|
+
const target = program.command("target").description("Cluaupp Roblox target profile");
|
|
134
|
+
target
|
|
135
|
+
.command("info")
|
|
136
|
+
.description("Print target identity and schema version")
|
|
137
|
+
.action(() => {
|
|
138
|
+
const profile = (0, index_js_1.buildRobloxTargetProfile)({ skipValidate: true });
|
|
139
|
+
console.log(JSON.stringify({
|
|
140
|
+
target: "roblox",
|
|
141
|
+
schemaVersion: index_js_1.ROBLOX_TARGET_SCHEMA_VERSION,
|
|
142
|
+
cluaupp: package_info_js_1.pkg.version,
|
|
143
|
+
robloxApiVersion: profile.robloxApiVersion,
|
|
144
|
+
classes: Object.keys(profile.classes).length,
|
|
145
|
+
enums: Object.keys(profile.enums).length,
|
|
146
|
+
datatypes: Object.keys(profile.datatypes).length,
|
|
147
|
+
services: Object.keys(profile.services).length,
|
|
148
|
+
unsupported: profile.unsupported.length,
|
|
149
|
+
}, null, "\t"));
|
|
150
|
+
});
|
|
151
|
+
target
|
|
152
|
+
.command("doctor")
|
|
153
|
+
.description("Full platform check: registry, lock, DataModel, parallel, authority, security, graph, Flare")
|
|
154
|
+
.argument("[folder]", "game root", ".")
|
|
155
|
+
.action((folder) => {
|
|
156
|
+
const root = node_path_1.default.resolve(folder);
|
|
157
|
+
const report = (0, index_js_1.runDoctor)(root);
|
|
158
|
+
console.log(JSON.stringify(report, null, "\t"));
|
|
159
|
+
if (!report.ok) {
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
target
|
|
164
|
+
.command("capabilities")
|
|
165
|
+
.description("Print Context Safety capability profile (runContext rules)")
|
|
166
|
+
.action(() => {
|
|
167
|
+
const pathOut = (0, index_js_1.writeCapabilityProfile)();
|
|
168
|
+
console.log(JSON.stringify((0, index_js_1.builtinCapabilityProfile)(), null, "\t"));
|
|
169
|
+
console.log("wrote", pathOut);
|
|
170
|
+
});
|
|
171
|
+
target
|
|
172
|
+
.command("check-context")
|
|
173
|
+
.description("Scan a .clpp file for Context Safety violations")
|
|
174
|
+
.argument("<file>", "CL++ source path")
|
|
175
|
+
.action((file) => {
|
|
176
|
+
const abs = node_path_1.default.resolve(file);
|
|
177
|
+
const source = node_fs_1.default.readFileSync(abs, "utf8");
|
|
178
|
+
const violations = (0, index_js_1.checkContextSafety)(source, abs);
|
|
179
|
+
console.log(JSON.stringify(violations, null, "\t"));
|
|
180
|
+
if (violations.some((v) => v.severity === "error")) {
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
target
|
|
185
|
+
.command("datamodel")
|
|
186
|
+
.description("Build Typed DataModel profile + generated datamodel.clh from Rojo project")
|
|
187
|
+
.argument("[folder]", "game root with default.project.json", ".")
|
|
188
|
+
.option("-r, --rojo <path>", "Rojo project json")
|
|
189
|
+
.action((folder, options) => {
|
|
190
|
+
const root = node_path_1.default.resolve(folder);
|
|
191
|
+
const result = (0, index_js_1.writeDatamodelArtifacts)(root, { projectJson: options.rojo });
|
|
192
|
+
if (!result) {
|
|
193
|
+
console.error("cluaupp target datamodel: no default.project.json in", root);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
const paths = Object.keys(result.profile.byPath).filter((p) => p !== "DataModel");
|
|
197
|
+
console.log(JSON.stringify({
|
|
198
|
+
project: result.profile.projectName,
|
|
199
|
+
nodes: paths.length,
|
|
200
|
+
profile: result.profilePath,
|
|
201
|
+
header: result.headerPath,
|
|
202
|
+
sample: paths.slice(0, 20),
|
|
203
|
+
}, null, "\t"));
|
|
204
|
+
});
|
|
205
|
+
target
|
|
206
|
+
.command("check-datamodel")
|
|
207
|
+
.description("Scan a .clpp file for Typed DataModel path violations")
|
|
208
|
+
.argument("<file>", "CL++ source path")
|
|
209
|
+
.option("-r, --rojo <folder>", "game root with default.project.json", ".")
|
|
210
|
+
.action((file, options) => {
|
|
211
|
+
const abs = node_path_1.default.resolve(file);
|
|
212
|
+
const root = node_path_1.default.resolve(options.rojo || ".");
|
|
213
|
+
const profile = (0, index_js_1.buildDatamodelProfile)(root);
|
|
214
|
+
if (!profile) {
|
|
215
|
+
console.error("cluaupp target check-datamodel: no default.project.json in", root);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
const source = node_fs_1.default.readFileSync(abs, "utf8");
|
|
219
|
+
const violations = (0, index_js_1.checkDatamodelPaths)(source, profile);
|
|
220
|
+
console.log(JSON.stringify(violations, null, "\t"));
|
|
221
|
+
if (violations.some((v) => v.severity === "error")) {
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
target
|
|
226
|
+
.command("check-parallel")
|
|
227
|
+
.description("Scan a .clpp file for Unsafe API use in parallel regions")
|
|
228
|
+
.argument("<file>", "CL++ source path")
|
|
229
|
+
.action((file) => {
|
|
230
|
+
const abs = node_path_1.default.resolve(file);
|
|
231
|
+
const source = node_fs_1.default.readFileSync(abs, "utf8");
|
|
232
|
+
const diags = (0, index_js_1.checkParallelSafety)(source, abs);
|
|
233
|
+
console.log(JSON.stringify(diags, null, "\t"));
|
|
234
|
+
if (diags.some((d) => d.severity === "error"))
|
|
235
|
+
process.exit(1);
|
|
236
|
+
});
|
|
237
|
+
target
|
|
238
|
+
.command("graph")
|
|
239
|
+
.description("Print project include graph and cycles")
|
|
240
|
+
.argument("[folder]", "game root", ".")
|
|
241
|
+
.action((folder) => {
|
|
242
|
+
console.log(JSON.stringify((0, index_js_1.buildProjectGraph)(node_path_1.default.resolve(folder)), null, "\t"));
|
|
243
|
+
});
|
|
244
|
+
target
|
|
245
|
+
.command("verify")
|
|
246
|
+
.description("Alias of api verify + profile validate")
|
|
247
|
+
.action(() => {
|
|
248
|
+
const issues = (0, index_js_1.validateCurrent)().filter((i) => i.severity === "error");
|
|
249
|
+
const lock = (0, index_js_1.verifyLock)();
|
|
250
|
+
if (issues.length || !lock.ok) {
|
|
251
|
+
console.error("cluaupp target verify: FAILED");
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
console.log("cluaupp target verify: OK");
|
|
255
|
+
});
|
|
256
|
+
target
|
|
257
|
+
.command("diff")
|
|
258
|
+
.argument("<snapshot>", "previous profile JSON")
|
|
259
|
+
.action((snapshot) => {
|
|
260
|
+
console.log(JSON.stringify((0, index_js_1.apiDiffAgainstSnapshot)(node_path_1.default.resolve(snapshot)), null, "\t"));
|
|
261
|
+
});
|
|
262
|
+
target
|
|
263
|
+
.command("lock")
|
|
264
|
+
.description("Regenerate lock from current sources (via api generate)")
|
|
265
|
+
.action(() => {
|
|
266
|
+
runGenerate();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function registerPlatformCommands(program) {
|
|
270
|
+
program
|
|
271
|
+
.command("optimize")
|
|
272
|
+
.description("Advisor + optional apply: native pragmas, SoA layout codegen")
|
|
273
|
+
.argument("[folder]", "game root", ".")
|
|
274
|
+
.option("--profile <file>", "Rank advice with cluaupp.profile.json (PGO)")
|
|
275
|
+
.option("--apply", "Write #pragma native (and --layout pragmas) into sources")
|
|
276
|
+
.option("--layout", "With --apply: #pragma layout soa + emit .cluaupp/generated/soa/*Soa.luau")
|
|
277
|
+
.option("--buffer", "With --layout: pack f32/i32 columns into buffer")
|
|
278
|
+
.action((folder, opts) => {
|
|
279
|
+
const root = node_path_1.default.resolve(folder);
|
|
280
|
+
const src = node_path_1.default.join(root, "src");
|
|
281
|
+
const files = node_fs_1.default.existsSync(src) ? (0, paths_js_1.collectSources)(src) : [];
|
|
282
|
+
const profilePath = opts.profile ? node_path_1.default.resolve(root, opts.profile) : (0, pgo_js_1.defaultProfilePath)(root);
|
|
283
|
+
const profile = (0, pgo_js_1.loadProfile)(profilePath);
|
|
284
|
+
const advice = [];
|
|
285
|
+
let appliedCount = 0;
|
|
286
|
+
for (const file of files) {
|
|
287
|
+
const rel = node_path_1.default.relative(root, file).replace(/\\/g, "/");
|
|
288
|
+
const source = node_fs_1.default.readFileSync(file, "utf8");
|
|
289
|
+
const ranked = (0, pgo_js_1.rankAdvice)((0, index_js_1.adviseOptimizer)(source, rel), profile);
|
|
290
|
+
for (const a of ranked) {
|
|
291
|
+
advice.push({ file: rel, ...a });
|
|
292
|
+
}
|
|
293
|
+
if (opts.apply) {
|
|
294
|
+
const result = (0, optimizer_apply_js_1.applyOptimizerHints)(source, rel, profile, {
|
|
295
|
+
layout: opts.layout === true,
|
|
296
|
+
useBuffer: opts.buffer === true,
|
|
297
|
+
projectRoot: root,
|
|
298
|
+
});
|
|
299
|
+
if (result.changed) {
|
|
300
|
+
node_fs_1.default.writeFileSync(file, result.source, "utf8");
|
|
301
|
+
appliedCount += result.applied.length;
|
|
302
|
+
console.error(`cluaupp optimize --apply: ${rel}: ${result.applied.join(", ")}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (opts.apply && opts.layout) {
|
|
307
|
+
const plans = (0, optimizer_soa_js_1.collectSoaPlansFromProject)(root);
|
|
308
|
+
(0, optimizer_soa_js_1.writeSoaArtifacts)(root, plans, { useBuffer: opts.buffer === true });
|
|
309
|
+
}
|
|
310
|
+
if (opts.apply) {
|
|
311
|
+
console.error(`cluaupp optimize --apply: ${appliedCount} hint(s)`);
|
|
312
|
+
}
|
|
313
|
+
console.log(JSON.stringify(advice, null, "\t"));
|
|
314
|
+
});
|
|
315
|
+
program
|
|
316
|
+
.command("bridge")
|
|
317
|
+
.description("Studio↔IDE HTTP bridge (default :3847) — Open IDE from CluauppNav plugin")
|
|
318
|
+
.argument("[folder]", "game root", ".")
|
|
319
|
+
.option("-p, --port <n>", "Port", String(studio_bridge_js_1.BRIDGE_DEFAULT_PORT))
|
|
320
|
+
.action((folder, opts) => {
|
|
321
|
+
const root = node_path_1.default.resolve(folder);
|
|
322
|
+
const port = Number(opts.port) || studio_bridge_js_1.BRIDGE_DEFAULT_PORT;
|
|
323
|
+
const server = (0, studio_bridge_js_1.startStudioBridge)({
|
|
324
|
+
port,
|
|
325
|
+
projectRoot: root,
|
|
326
|
+
onEvent: (ev) => {
|
|
327
|
+
console.log(`cluaupp bridge: ${ev.type}`, ev.path || ev.message || "", ev.line ? `:${ev.line}` : "");
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
console.log(`cluaupp bridge: http://127.0.0.1:${server.port} (project ${root})`);
|
|
331
|
+
console.log("Keep this process running. Studio plugin → Open IDE / errors POST here.");
|
|
332
|
+
});
|
|
333
|
+
program
|
|
334
|
+
.command("profile")
|
|
335
|
+
.description("PGO: write template, or ingest Studio/playtest JSONL into cluaupp.profile.json")
|
|
336
|
+
.argument("[folder]", "game root", ".")
|
|
337
|
+
.option("--ingest <file>", "Merge JSON/JSONL profile events into cluaupp.profile.json")
|
|
338
|
+
.action((folder, opts) => {
|
|
339
|
+
const root = node_path_1.default.resolve(folder);
|
|
340
|
+
if (opts.ingest) {
|
|
341
|
+
const { profilePath, merged, profile } = (0, index_js_1.ingestProfile)(root, opts.ingest);
|
|
342
|
+
console.log(`cluaupp profile ingest: ${merged} event(s) → ${profilePath}`);
|
|
343
|
+
console.log(JSON.stringify({ hot: profile.hot, structs: profile.structs }, null, "\t"));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const file = (0, pgo_js_1.writeProfileTemplate)(root);
|
|
347
|
+
console.log("cluaupp profile:", file);
|
|
348
|
+
});
|
|
349
|
+
program
|
|
350
|
+
.command("check-authority")
|
|
351
|
+
.description("Authority rules + call-graph (CLUAU-AUTH*)")
|
|
352
|
+
.argument("[folder]", "game root", ".")
|
|
353
|
+
.action((folder) => {
|
|
354
|
+
const root = node_path_1.default.resolve(folder);
|
|
355
|
+
const src = node_path_1.default.join(root, "src");
|
|
356
|
+
const files = node_fs_1.default.existsSync(src) ? (0, paths_js_1.collectSources)(src) : [];
|
|
357
|
+
const policy = (0, index_js_1.loadPlatformPolicy)(root);
|
|
358
|
+
const all = [...(0, index_js_1.checkAuthorityGraph)(root, "src", policy)];
|
|
359
|
+
for (const file of files) {
|
|
360
|
+
const rel = node_path_1.default.relative(root, file).replace(/\\/g, "/");
|
|
361
|
+
all.push(...(0, index_js_1.checkAuthority)(node_fs_1.default.readFileSync(file, "utf8"), rel, policy));
|
|
362
|
+
}
|
|
363
|
+
console.log(JSON.stringify(all, null, "\t"));
|
|
364
|
+
if (all.some((d) => d.severity === "error"))
|
|
365
|
+
process.exit(1);
|
|
366
|
+
});
|
|
367
|
+
program
|
|
368
|
+
.command("docs")
|
|
369
|
+
.description("Generate .cluaupp/PROJECT.md from DataModel + graph + Flare + optimizer advice")
|
|
370
|
+
.argument("[folder]", "game root", ".")
|
|
371
|
+
.action((folder) => {
|
|
372
|
+
const { outPath } = (0, project_docs_js_1.generateProjectDocs)(node_path_1.default.resolve(folder));
|
|
373
|
+
console.log("cluaupp docs:", outPath);
|
|
374
|
+
});
|
|
375
|
+
program
|
|
376
|
+
.command("security")
|
|
377
|
+
.description("Static security pattern scan (warnings)")
|
|
378
|
+
.argument("[folder]", "game root", ".")
|
|
379
|
+
.action((folder) => {
|
|
380
|
+
const root = node_path_1.default.resolve(folder);
|
|
381
|
+
const src = node_path_1.default.join(root, "src");
|
|
382
|
+
const files = node_fs_1.default.existsSync(src) ? (0, paths_js_1.collectSources)(src) : [];
|
|
383
|
+
const all = [];
|
|
384
|
+
for (const file of files) {
|
|
385
|
+
const rel = node_path_1.default.relative(root, file).replace(/\\/g, "/");
|
|
386
|
+
all.push(...(0, index_js_1.checkSecurity)(node_fs_1.default.readFileSync(file, "utf8"), rel));
|
|
387
|
+
}
|
|
388
|
+
console.log(JSON.stringify(all, null, "\t"));
|
|
389
|
+
});
|
|
390
|
+
program
|
|
391
|
+
.command("analyze")
|
|
392
|
+
.description("Alias of target doctor (full platform analysis)")
|
|
393
|
+
.argument("[folder]", "game root", ".")
|
|
394
|
+
.action((folder) => {
|
|
395
|
+
const report = (0, index_js_1.runDoctor)(node_path_1.default.resolve(folder));
|
|
396
|
+
console.log(JSON.stringify(report, null, "\t"));
|
|
397
|
+
if (!report.ok)
|
|
398
|
+
process.exit(1);
|
|
399
|
+
});
|
|
400
|
+
program
|
|
401
|
+
.command("add")
|
|
402
|
+
.description("Thin Wally wrapper: runs `wally add` when wally is on PATH")
|
|
403
|
+
.argument("<package>", "wally package spec")
|
|
404
|
+
.action((pkgName) => {
|
|
405
|
+
const r = (0, node_child_process_1.spawnSync)("wally", ["add", pkgName], { stdio: "inherit", shell: true });
|
|
406
|
+
if (r.error || (r.status ?? 1) !== 0) {
|
|
407
|
+
console.error("cluaupp add: install Wally and retry, or edit wally.toml by hand");
|
|
408
|
+
process.exit(r.status ?? 1);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function runGenerate(dump, skipHeaders, skipLuau, skipDocs = true) {
|
|
413
|
+
const started = Date.now();
|
|
414
|
+
const result = (0, index_js_1.generateAll)({ dumpPath: dump, skipHeaders, skipLuau, skipDocs });
|
|
415
|
+
console.log(`cluaupp api generate: schema v${result.profile.schemaVersion}, ${Object.keys(result.profile.classes).length} classes, ${Object.keys(result.profile.enums).length} enums, ${Object.keys(result.profile.datatypes).length} datatypes (${Date.now() - started}ms)`);
|
|
416
|
+
console.log("manifest:", result.manifestPath);
|
|
417
|
+
console.log("lock:", result.lockPath);
|
|
418
|
+
if (result.lspIndexPath) {
|
|
419
|
+
console.log("lsp-index:", result.lspIndexPath);
|
|
420
|
+
}
|
|
421
|
+
}
|
package/generated/cli.js
CHANGED
|
@@ -22,6 +22,7 @@ const project_js_1 = require("./utils/project.js");
|
|
|
22
22
|
Object.defineProperty(exports, "init", { enumerable: true, get: function () { return project_js_1.init; } });
|
|
23
23
|
Object.defineProperty(exports, "watch", { enumerable: true, get: function () { return project_js_1.watch; } });
|
|
24
24
|
const transpile_js_1 = require("./transpile.js");
|
|
25
|
+
const api_cli_js_1 = require("./api-cli.js");
|
|
25
26
|
const program = new commander_1.Command();
|
|
26
27
|
exports.program = program;
|
|
27
28
|
program
|
|
@@ -53,20 +54,27 @@ program
|
|
|
53
54
|
.option("-o, --output <path>", "Luau file or directory")
|
|
54
55
|
.option("-r, --rojo <path>", "Path to Rojo default.project.json", "./default.project.json")
|
|
55
56
|
.option("--strict", "Emit --!strict")
|
|
56
|
-
.option("--format", "
|
|
57
|
+
.option("--format", "Also run StyLua if it is on PATH")
|
|
57
58
|
.option("--analyze", "Run luau-analyze on output")
|
|
59
|
+
.option("--frozen", "Hermetic: fail if API lock / Flare versions / component contracts drift")
|
|
60
|
+
.option("--no-incremental", "Disable compile cache under .cluaupp/compile-cache")
|
|
61
|
+
.option("-j, --jobs <n>", "Parallel transpile workers (default: CPU-bounded; env CLUAUPP_JOBS)", (v) => Number(v))
|
|
58
62
|
.action(async (folder, options) => {
|
|
59
63
|
if (options.input) {
|
|
60
64
|
await buildInput(options);
|
|
61
65
|
return;
|
|
62
66
|
}
|
|
63
67
|
try {
|
|
64
|
-
|
|
68
|
+
const opts = {
|
|
65
69
|
format: options.format === true,
|
|
66
70
|
analyze: options.analyze === true,
|
|
67
71
|
rojo: options.rojo,
|
|
68
72
|
strict: options.strict === true,
|
|
69
|
-
|
|
73
|
+
frozen: options.frozen === true,
|
|
74
|
+
incremental: options.incremental !== false,
|
|
75
|
+
jobs: Number.isFinite(options.jobs) && options.jobs > 0 ? options.jobs : undefined,
|
|
76
|
+
};
|
|
77
|
+
await (0, project_js_1.buildAsync)(node_path_1.default.resolve(process.cwd(), folder), opts);
|
|
70
78
|
}
|
|
71
79
|
catch (err) {
|
|
72
80
|
console.error(err instanceof Error ? err.message : err);
|
|
@@ -78,7 +86,7 @@ program
|
|
|
78
86
|
.description("rebuild on save")
|
|
79
87
|
.argument("[folder]", "project folder", ".")
|
|
80
88
|
.option("-r, --rojo <path>", "Path to Rojo default.project.json", "./default.project.json")
|
|
81
|
-
.option("--format", "
|
|
89
|
+
.option("--format", "Also run StyLua if it is on PATH")
|
|
82
90
|
.action((folder, options) => {
|
|
83
91
|
try {
|
|
84
92
|
(0, project_js_1.watch)(node_path_1.default.resolve(process.cwd(), folder), {
|
|
@@ -93,7 +101,7 @@ program
|
|
|
93
101
|
});
|
|
94
102
|
program
|
|
95
103
|
.command("lsp")
|
|
96
|
-
.description("Language server stdio
|
|
104
|
+
.description("Language server stdio — Flare `.flare` IntelliSense. CL++ still uses `clpp setup`.")
|
|
97
105
|
.argument("[folder]", "project folder", ".")
|
|
98
106
|
.action((folder) => {
|
|
99
107
|
(0, lsp_js_1.start)({ projectRoot: node_path_1.default.resolve(process.cwd(), folder) });
|
|
@@ -101,7 +109,7 @@ program
|
|
|
101
109
|
program
|
|
102
110
|
.command("intellisense")
|
|
103
111
|
.alias("intelisense")
|
|
104
|
-
.description("
|
|
112
|
+
.description("Install schema IntelliSense (.flare .hive .mint .bloom .helm .shift .axiom) + sync .vscode; CL++ via clpp install")
|
|
105
113
|
.argument("[folder]", "project folder", ".")
|
|
106
114
|
.action(async (folder) => {
|
|
107
115
|
try {
|
|
@@ -138,6 +146,9 @@ program
|
|
|
138
146
|
process.exit(1);
|
|
139
147
|
}
|
|
140
148
|
});
|
|
149
|
+
(0, api_cli_js_1.registerApiCommands)(program);
|
|
150
|
+
(0, api_cli_js_1.registerTargetCommands)(program);
|
|
151
|
+
(0, api_cli_js_1.registerPlatformCommands)(program);
|
|
141
152
|
async function buildInput(options) {
|
|
142
153
|
if (!options.input || !options.output) {
|
|
143
154
|
console.error("[Erro] --input e --output são obrigatórios neste modo.");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/** Stable CL++ ↔ Cluaupp contract (CL++ 0.
|
|
2
|
+
/** Stable CL++ ↔ Cluaupp contract (CL++ 0.8.x). Cluaupp invokes the `clpp` binary. */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.CLPP_INSTALL_HINT = exports.MIN_CLPP_VERSION = void 0;
|
|
5
|
-
exports.MIN_CLPP_VERSION = "0.
|
|
6
|
-
exports.CLPP_INSTALL_HINT = "Install CL++ 0.
|
|
5
|
+
exports.MIN_CLPP_VERSION = "0.8.0";
|
|
6
|
+
exports.CLPP_INSTALL_HINT = "Install CL++ 0.8.0+ (`clpp` from https://github.com/KartzRbx/CLPP/releases). Put it on PATH. Prefer `import { Name } from \"./x.clh\"` for language modules; angle `#include <clpp/…>` stays for host prelude. Override with CLPP or CLPP_PATH.";
|