@flamework-experimental/transformer 2.0.0-alpha.0

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 (72) hide show
  1. package/README.md +66 -0
  2. package/flamework-schema.json +76 -0
  3. package/flamework.config.schema.json +197 -0
  4. package/out/classes/buildInfo.js +467 -0
  5. package/out/classes/diagnostics.js +110 -0
  6. package/out/classes/logger.js +201 -0
  7. package/out/classes/nodeMetadata.js +232 -0
  8. package/out/classes/transformState.js +623 -0
  9. package/out/index.js +75 -0
  10. package/out/transformations/expressions/transformAccessExpression.js +35 -0
  11. package/out/transformations/expressions/transformBinaryExpression.js +57 -0
  12. package/out/transformations/expressions/transformCallExpression.js +33 -0
  13. package/out/transformations/expressions/transformDeleteExpression.js +22 -0
  14. package/out/transformations/expressions/transformNewExpression.js +17 -0
  15. package/out/transformations/expressions/transformUnaryExpression.js +63 -0
  16. package/out/transformations/macros/intrinsics/components.js +64 -0
  17. package/out/transformations/macros/intrinsics/env.js +31 -0
  18. package/out/transformations/macros/intrinsics/guards.js +43 -0
  19. package/out/transformations/macros/intrinsics/inlining.js +22 -0
  20. package/out/transformations/macros/intrinsics/networking.js +131 -0
  21. package/out/transformations/macros/intrinsics/parameters.js +81 -0
  22. package/out/transformations/macros/intrinsics/paths.js +42 -0
  23. package/out/transformations/macros/updateComponentConfig.js +409 -0
  24. package/out/transformations/plugins/nodeFactory.js +159 -0
  25. package/out/transformations/plugins/pluginHost.js +235 -0
  26. package/out/transformations/plugins/typeFacade.js +242 -0
  27. package/out/transformations/statements/transformClassDeclaration.js +282 -0
  28. package/out/transformations/transformExpression.js +34 -0
  29. package/out/transformations/transformFile.js +78 -0
  30. package/out/transformations/transformNetworkingCall.js +566 -0
  31. package/out/transformations/transformNode.js +27 -0
  32. package/out/transformations/transformStatement.js +57 -0
  33. package/out/transformations/transformStatementList.js +64 -0
  34. package/out/transformations/transformUserMacro.js +698 -0
  35. package/out/transformer.js +52 -0
  36. package/out/util/cache.js +10 -0
  37. package/out/util/constants.js +5 -0
  38. package/out/util/diagnosticsUtils.js +112 -0
  39. package/out/util/env.js +267 -0
  40. package/out/util/factory.js +583 -0
  41. package/out/util/functions/addLeadingComment.js +13 -0
  42. package/out/util/functions/arePathsEqual.js +14 -0
  43. package/out/util/functions/assert.js +17 -0
  44. package/out/util/functions/buildGuardFromType.js +713 -0
  45. package/out/util/functions/buildInstanceShape.js +156 -0
  46. package/out/util/functions/buildSerializerFromType.js +2309 -0
  47. package/out/util/functions/createPathTranslator.js +54 -0
  48. package/out/util/functions/emitTypescriptMismatch.js +80 -0
  49. package/out/util/functions/getDeclarationName.js +23 -0
  50. package/out/util/functions/getDeclarationOfType.js +7 -0
  51. package/out/util/functions/getIndexExpression.js +16 -0
  52. package/out/util/functions/getInstanceTypeFromType.js +75 -0
  53. package/out/util/functions/getNodeList.js +6 -0
  54. package/out/util/functions/getPackageJson.js +44 -0
  55. package/out/util/functions/getSuperClasses.js +51 -0
  56. package/out/util/functions/isAttributesAccess.js +23 -0
  57. package/out/util/functions/isCleanBuildDirectory.js +13 -0
  58. package/out/util/functions/isDefinedType.js +16 -0
  59. package/out/util/functions/isPathDescendantOf.js +25 -0
  60. package/out/util/functions/isTupleType.js +10 -0
  61. package/out/util/functions/parseCommandLine.js +31 -0
  62. package/out/util/functions/shuffle.js +39 -0
  63. package/out/util/functions/tryResolve.js +15 -0
  64. package/out/util/functions/validateConstraintMetadata.js +60 -0
  65. package/out/util/packages.js +12 -0
  66. package/out/util/projectConfig.js +221 -0
  67. package/out/util/schema.js +80 -0
  68. package/out/util/tsInternals.js +16 -0
  69. package/out/util/uid.js +227 -0
  70. package/package.json +45 -0
  71. package/rojo-schema.json +34 -0
  72. package/types.d.ts +4 -0
@@ -0,0 +1,623 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __values = (this && this.__values) || function(o) {
14
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
15
+ if (m) return m.call(o);
16
+ if (o && typeof o.length === "number") return {
17
+ next: function () {
18
+ if (o && i >= o.length) o = void 0;
19
+ return { value: o && o[i++], done: !o };
20
+ }
21
+ };
22
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
23
+ };
24
+ var __read = (this && this.__read) || function (o, n) {
25
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
26
+ if (!m) return o;
27
+ var i = m.call(o), r, ar = [], e;
28
+ try {
29
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
30
+ }
31
+ catch (error) { e = { error: error }; }
32
+ finally {
33
+ try {
34
+ if (r && !r.done && (m = i["return"])) m.call(i);
35
+ }
36
+ finally { if (e) throw e.error; }
37
+ }
38
+ return ar;
39
+ };
40
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
41
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
42
+ if (ar || !(i in from)) {
43
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
44
+ ar[i] = from[i];
45
+ }
46
+ }
47
+ return to.concat(ar || Array.prototype.slice.call(from));
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.TransformState = void 0;
54
+ var typescript_1 = __importDefault(require("typescript"));
55
+ var fs_1 = __importDefault(require("fs"));
56
+ var crypto_1 = __importDefault(require("crypto"));
57
+ var path_1 = __importDefault(require("path"));
58
+ var hashids_1 = __importDefault(require("hashids"));
59
+ var transformNode_1 = require("../transformations/transformNode");
60
+ var cache_1 = require("../util/cache");
61
+ var getPackageJson_1 = require("../util/functions/getPackageJson");
62
+ var buildInfo_1 = require("./buildInfo");
63
+ var logger_1 = require("./logger");
64
+ var factory_1 = require("../util/factory");
65
+ var isPathDescendantOf_1 = require("../util/functions/isPathDescendantOf");
66
+ var isCleanBuildDirectory_1 = require("../util/functions/isCleanBuildDirectory");
67
+ var parseCommandLine_1 = require("../util/functions/parseCommandLine");
68
+ var createPathTranslator_1 = require("../util/functions/createPathTranslator");
69
+ var arePathsEqual_1 = require("../util/functions/arePathsEqual");
70
+ var nodeMetadata_1 = require("./nodeMetadata");
71
+ var rojo_resolver_1 = require("@roblox-ts/rojo-resolver");
72
+ var assert_1 = require("../util/functions/assert");
73
+ var shuffle_1 = require("../util/functions/shuffle");
74
+ var glob_1 = __importDefault(require("glob"));
75
+ var pluginHost_1 = require("../transformations/plugins/pluginHost");
76
+ var tryResolve_1 = require("../util/functions/tryResolve");
77
+ var projectConfig_1 = require("../util/projectConfig");
78
+ var diagnostics_1 = require("./diagnostics");
79
+ var packages_1 = require("../util/packages");
80
+ var TransformState = /** @class */ (function () {
81
+ function TransformState(program, context, inlineConfig) {
82
+ var _a, _b, _c, _d, _e, _f;
83
+ var _g, _h;
84
+ this.program = program;
85
+ this.context = context;
86
+ this.parsedCommandLine = (0, parseCommandLine_1.parseCommandLine)();
87
+ this.currentDirectory = this.parsedCommandLine.project;
88
+ this.options = this.program.getCompilerOptions();
89
+ this.srcDir = (_a = this.options.rootDir) !== null && _a !== void 0 ? _a : this.currentDirectory;
90
+ this.outDir = (_b = this.options.outDir) !== null && _b !== void 0 ? _b : this.currentDirectory;
91
+ this.rootDirs = this.options.rootDirs ? this.options.rootDirs : [this.srcDir];
92
+ this.typeChecker = this.program.getTypeChecker();
93
+ this.isUserMacroCache = new Map();
94
+ this.nextRootStatements = new Array();
95
+ /**
96
+ * Whether this process started from the previous build's `flamework.build` rather than a fresh
97
+ * one, which an incremental build does so that the files it does not recompile keep their ids.
98
+ * Under obfuscation that also keeps the ids a release was meant to rotate.
99
+ */
100
+ this.buildInfoReused = false;
101
+ this.fileImports = new Map();
102
+ this.prereqStack = new Array();
103
+ var _j = (0, getPackageJson_1.getPackageJson)(this.currentDirectory), packageJson = _j.result, directory = _j.directory;
104
+ this.rootDirectory = directory;
105
+ (0, assert_1.assert)(packageJson.name);
106
+ // Read once per process: a watcher keeps the config and environment it started with, since
107
+ // only the files that changed are recompiled and the rest would disagree with them. Every
108
+ // later compilation reads again only to notice a change and ask for a restart.
109
+ var loaded = (0, projectConfig_1.loadProjectConfig)(this.currentDirectory, this.rootDirectory, inlineConfig);
110
+ var fingerprint = (0, projectConfig_1.fingerprintProjectConfig)(loaded);
111
+ if (cache_1.Cache.projectConfig === undefined) {
112
+ cache_1.Cache.projectConfig = loaded;
113
+ cache_1.Cache.projectConfigFingerprint = fingerprint;
114
+ }
115
+ else if (cache_1.Cache.projectConfigFingerprint !== fingerprint) {
116
+ logger_1.Logger.warn("flamework.config.json or .env changed since the watcher started", "The values it started with are still in use; restart the watcher to apply the change.");
117
+ }
118
+ var effective = cache_1.Cache.projectConfig;
119
+ this.config = __assign({}, effective.config);
120
+ this.configPath = effective.configPath;
121
+ this.projectConfig = effective.project;
122
+ this.env = effective.env;
123
+ this.setupRojo();
124
+ this.setupBuildInfo();
125
+ (_c = (_g = this.config).idGenerationMode) !== null && _c !== void 0 ? _c : (_g.idGenerationMode = this.config.obfuscation ? "obfuscated" : "full");
126
+ var previousMode = this.buildInfo.setIdGenerationMode(this.config.idGenerationMode);
127
+ if (previousMode !== undefined) {
128
+ logger_1.Logger.info("idGenerationMode changed from '".concat(previousMode, "' to '").concat(this.config.idGenerationMode, "'; every identifier is regenerated"));
129
+ }
130
+ // Obfuscation is only worth something if a release's ids differ from the last release's.
131
+ // A plain build recreates flamework.build, and with it the salt and the build seed, so
132
+ // that holds on its own; these are the two ways of undoing it.
133
+ if (this.config.obfuscation && cache_1.Cache.isInitialCompile) {
134
+ if (this.config.salt !== undefined) {
135
+ logger_1.Logger.warn("transformer.salt is set with obfuscation on", "A fixed salt gives every build the same obfuscated ids; leave it unset so each build gets fresh ones.");
136
+ }
137
+ if (this.buildInfoReused) {
138
+ logger_1.Logger.warn("obfuscated ids were kept from the previous build", "This is an incremental build, so files that do not recompile keep their ids and the rest have to match.", "Delete ".concat((_d = this.options.tsBuildInfoFile) !== null && _d !== void 0 ? _d : "the tsbuildinfo", " before a release build to rotate every id."));
139
+ }
140
+ }
141
+ this.packageName = packageJson.name;
142
+ this.isGame = !this.packageName.startsWith("@");
143
+ this.includeDirectory = this.getIncludePath();
144
+ if (!this.isGame)
145
+ (_e = (_h = this.config).hashPrefix) !== null && _e !== void 0 ? _e : (_h.hashPrefix = this.packageName);
146
+ this.buildInfo.setIdentifierPrefix(this.config.hashPrefix);
147
+ if (((_f = this.config.hashPrefix) === null || _f === void 0 ? void 0 : _f.startsWith("$")) && !this.packageName.startsWith(packages_1.FLAMEWORK_SCOPE)) {
148
+ throw new Error("The hashPrefix $ is used internally by Flamework");
149
+ }
150
+ cache_1.Cache.isInitialCompile = false;
151
+ this.pluginHost = (0, pluginHost_1.createPluginHost)(this);
152
+ }
153
+ TransformState.prototype.setupBuildInfo = function () {
154
+ var e_1, _a, e_2, _b;
155
+ var _c;
156
+ var baseBuildInfo = buildInfo_1.BuildInfo.fromDirectory(this.currentDirectory);
157
+ if (!baseBuildInfo || (cache_1.Cache.isInitialCompile && (0, isCleanBuildDirectory_1.isCleanBuildDirectory)(this.options))) {
158
+ if (this.options.incremental && this.options.tsBuildInfoFile) {
159
+ if (typescript_1.default.sys.fileExists(this.options.tsBuildInfoFile)) {
160
+ throw new Error("Flamework cannot be built in a dirty environment, please delete your tsbuildinfo");
161
+ }
162
+ }
163
+ baseBuildInfo = new buildInfo_1.BuildInfo(path_1.default.join(this.currentDirectory, "flamework.build"));
164
+ }
165
+ else if (cache_1.Cache.isInitialCompile) {
166
+ this.buildInfoReused = true;
167
+ }
168
+ this.buildInfo = baseBuildInfo;
169
+ var candidates = (_c = cache_1.Cache.buildInfoCandidates) !== null && _c !== void 0 ? _c : [];
170
+ if (!cache_1.Cache.buildInfoCandidates) {
171
+ cache_1.Cache.buildInfoCandidates = candidates;
172
+ var candidatesSet = new Set();
173
+ try {
174
+ for (var _d = __values(this.program.getSourceFiles()), _e = _d.next(); !_e.done; _e = _d.next()) {
175
+ var file = _e.value;
176
+ var buildCandidate = buildInfo_1.BuildInfo.findCandidateUpper(path_1.default.dirname(file.fileName));
177
+ if (buildCandidate &&
178
+ !(0, arePathsEqual_1.arePathsEqual)(buildCandidate, baseBuildInfo.buildInfoPath) &&
179
+ !candidatesSet.has(buildCandidate)) {
180
+ candidatesSet.add(buildCandidate);
181
+ candidates.push(buildCandidate);
182
+ }
183
+ }
184
+ }
185
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
186
+ finally {
187
+ try {
188
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
189
+ }
190
+ finally { if (e_1) throw e_1.error; }
191
+ }
192
+ }
193
+ try {
194
+ for (var candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) {
195
+ var candidate = candidates_1_1.value;
196
+ var relativeCandidate = path_1.default.relative(this.currentDirectory, candidate);
197
+ var buildInfo = buildInfo_1.BuildInfo.fromPath(candidate);
198
+ if (buildInfo) {
199
+ logger_1.Logger.infoIfVerbose("Loaded buildInfo at ".concat(relativeCandidate, ", next id: ").concat(buildInfo.getLatestId()));
200
+ baseBuildInfo.addBuildInfo(buildInfo);
201
+ }
202
+ else {
203
+ logger_1.Logger.warn("Build info not valid at ".concat(relativeCandidate));
204
+ }
205
+ }
206
+ }
207
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
208
+ finally {
209
+ try {
210
+ if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
211
+ }
212
+ finally { if (e_2) throw e_2.error; }
213
+ }
214
+ };
215
+ TransformState.prototype.setupRojo = function () {
216
+ this.pathTranslator = (0, createPathTranslator_1.createPathTranslator)(this.program);
217
+ var rojoArgvIndex = process.argv.findIndex(function (v) { return v === "--rojo"; });
218
+ var rojoArg = rojoArgvIndex !== -1 ? process.argv[rojoArgvIndex + 1] : undefined;
219
+ var rojoConfig;
220
+ if (rojoArg && rojoArg !== "") {
221
+ rojoConfig = path_1.default.resolve(rojoArg);
222
+ }
223
+ else {
224
+ rojoConfig = rojo_resolver_1.RojoResolver.findRojoConfigFilePath(this.currentDirectory).path;
225
+ }
226
+ if (rojoConfig !== undefined) {
227
+ var rojoContents = fs_1.default.readFileSync(rojoConfig, { encoding: "ascii" });
228
+ var sum = crypto_1.default.createHash("md5").update(rojoContents).digest("hex");
229
+ if (sum === cache_1.Cache.rojoSum) {
230
+ this.rojoResolver = cache_1.Cache.rojoResolver;
231
+ }
232
+ else {
233
+ this.rojoResolver = rojo_resolver_1.RojoResolver.fromPath(rojoConfig);
234
+ cache_1.Cache.rojoSum = sum;
235
+ cache_1.Cache.rojoResolver = this.rojoResolver;
236
+ }
237
+ }
238
+ };
239
+ TransformState.prototype.getIncludePath = function () {
240
+ var includeArgvIndex = process.argv.findIndex(function (v) { return v === "--i" || v === "--includePath"; });
241
+ var includePath = includeArgvIndex !== -1 ? process.argv[includeArgvIndex + 1] : undefined;
242
+ return path_1.default.resolve(includePath || path_1.default.join(this.rootDirectory, "include"));
243
+ };
244
+ /**
245
+ * Since npm modules can be symlinked, TypeScript can resolve them to their real path (outside of the project directory.)
246
+ *
247
+ * This function attempts to convert the real path of *npm modules* back to their path inside the project directory.
248
+ * This is required to have RojoResolver be able to resolve files.
249
+ */
250
+ TransformState.prototype.toModulePath = function (filePath) {
251
+ // The module is under our root directory, so it's probably not symlinked.
252
+ if ((0, isPathDescendantOf_1.isPathDescendantOf)(filePath, this.rootDirectory)) {
253
+ return filePath;
254
+ }
255
+ var packageJsonPath = typescript_1.default.findPackageJson(filePath, typescript_1.default.sys);
256
+ if (!packageJsonPath) {
257
+ throw new Error("Unable to convert '".concat(filePath, "' to module."));
258
+ }
259
+ var packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, { encoding: "utf8" }));
260
+ return path_1.default.join(this.rootDirectory, "node_modules", packageJson.name, path_1.default.relative(path_1.default.dirname(packageJsonPath), filePath));
261
+ };
262
+ TransformState.prototype.calculateGlobs = function (globs) {
263
+ var _this = this;
264
+ if (!globs) {
265
+ return;
266
+ }
267
+ for (var pathGlob in globs) {
268
+ var paths = glob_1.default.sync(pathGlob, {
269
+ root: this.rootDirectory,
270
+ cwd: this.rootDirectory,
271
+ nocase: true,
272
+ });
273
+ globs[pathGlob] = paths.map(function (globPath) {
274
+ var outputPath = _this.pathTranslator.getOutputPath(globPath);
275
+ return path_1.default.relative(_this.rootDirectory, outputPath).replace(/\\/g, "/");
276
+ });
277
+ }
278
+ };
279
+ TransformState.prototype.convertGlobs = function (globs, luaOut, pkg) {
280
+ var e_3, _a;
281
+ var _b;
282
+ if (!globs) {
283
+ return;
284
+ }
285
+ var pkgInfo = pkg ? this.buildInfo.getBuildInfoFromPrefix(pkg) : undefined;
286
+ var root = pkgInfo ? path_1.default.dirname(this.toModulePath(pkgInfo.buildInfoPath)) : this.rootDirectory;
287
+ for (var pathGlob in globs) {
288
+ var paths = globs[pathGlob];
289
+ var rbxPaths = new Array();
290
+ try {
291
+ for (var paths_1 = (e_3 = void 0, __values(paths)), paths_1_1 = paths_1.next(); !paths_1_1.done; paths_1_1 = paths_1.next()) {
292
+ var globPath = paths_1_1.value;
293
+ var rbxPath = (_b = this.rojoResolver) === null || _b === void 0 ? void 0 : _b.getRbxPathFromFilePath(path_1.default.join(root, globPath));
294
+ if (rbxPath) {
295
+ rbxPaths.push(rbxPath);
296
+ }
297
+ }
298
+ }
299
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
300
+ finally {
301
+ try {
302
+ if (paths_1_1 && !paths_1_1.done && (_a = paths_1.return)) _a.call(paths_1);
303
+ }
304
+ finally { if (e_3) throw e_3.error; }
305
+ }
306
+ luaOut.set(pkgInfo ? pathGlob : this.obfuscateText(pathGlob, "addPaths"), rbxPaths);
307
+ }
308
+ };
309
+ TransformState.prototype.getFileId = function (file) {
310
+ return path_1.default.relative(this.rootDirectory, file.fileName).replace(/\\/g, "/");
311
+ };
312
+ TransformState.prototype.saveArtifacts = function () {
313
+ var e_4, _a, e_5, _b;
314
+ var _c, _d, _e, _f;
315
+ var start = new Date().getTime();
316
+ this.calculateGlobs((_c = this.buildInfo.getMetadata("globs")) === null || _c === void 0 ? void 0 : _c.paths);
317
+ if (this.isGame) {
318
+ var writtenFiles = new Map();
319
+ var files = ["globs.json", "config.json", "paths.json"];
320
+ // The runtime sections of flamework.config.json, for the packages to read at runtime.
321
+ var runtimeConfig = (0, projectConfig_1.getRuntimeConfig)(this.projectConfig);
322
+ if (runtimeConfig) {
323
+ // `testing.entry` is a source path in the file; the runner's cloud module needs the
324
+ // ModuleScript, so it is written as a tree path, resolved the way a path macro is.
325
+ var entry = (_d = runtimeConfig.testing) === null || _d === void 0 ? void 0 : _d.entry;
326
+ if (entry !== undefined) {
327
+ var sourcePath = entry.endsWith(".ts") ? entry : "".concat(entry, ".ts");
328
+ var outputPath = this.pathTranslator.getOutputPath(sourcePath);
329
+ var rbxPath = (_e = this.rojoResolver) === null || _e === void 0 ? void 0 : _e.getRbxPathFromFilePath(outputPath);
330
+ if (rbxPath === undefined) {
331
+ throw new Error("flamework.config.json: testing.entry '".concat(entry, "' is not in the Rojo tree; give the source path of the ModuleScript that exports ignite(), for example \"src/server/main\""));
332
+ }
333
+ runtimeConfig.testing = __assign(__assign({}, runtimeConfig.testing), { entry: rbxPath });
334
+ }
335
+ writtenFiles.set("config.json", JSON.stringify(runtimeConfig));
336
+ }
337
+ // Paths are emitted relative to the Rojo tree's root, which is `game` in a place but the
338
+ // model's own root in a plugin. The runtime finds that root by climbing from the include
339
+ // folder, so this records how far below the root the include folder sits.
340
+ var includeRbxPath = (_f = this.rojoResolver) === null || _f === void 0 ? void 0 : _f.getRbxPathFromFilePath(this.includeDirectory);
341
+ if (includeRbxPath !== undefined) {
342
+ writtenFiles.set("paths.json", JSON.stringify({ includeDepth: includeRbxPath.length }));
343
+ }
344
+ var packageGlobs = this.buildInfo.getChildrenMetadata("globs");
345
+ var globs = this.buildInfo.getMetadata("globs");
346
+ if (globs || packageGlobs.size > 0) {
347
+ var transformedGlobs = new Map();
348
+ this.convertGlobs(globs === null || globs === void 0 ? void 0 : globs.paths, transformedGlobs);
349
+ var transformedPackageGlobs = new Map();
350
+ try {
351
+ for (var packageGlobs_1 = __values(packageGlobs), packageGlobs_1_1 = packageGlobs_1.next(); !packageGlobs_1_1.done; packageGlobs_1_1 = packageGlobs_1.next()) {
352
+ var _g = __read(packageGlobs_1_1.value, 2), pkg = _g[0], packageGlob = _g[1];
353
+ var transformedGlobs_1 = new Map();
354
+ this.convertGlobs(packageGlob === null || packageGlob === void 0 ? void 0 : packageGlob.paths, transformedGlobs_1, pkg);
355
+ transformedPackageGlobs.set(pkg, Object.fromEntries(transformedGlobs_1));
356
+ }
357
+ }
358
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
359
+ finally {
360
+ try {
361
+ if (packageGlobs_1_1 && !packageGlobs_1_1.done && (_a = packageGlobs_1.return)) _a.call(packageGlobs_1);
362
+ }
363
+ finally { if (e_4) throw e_4.error; }
364
+ }
365
+ writtenFiles.set("globs.json", JSON.stringify({
366
+ game: Object.fromEntries(transformedGlobs),
367
+ packages: Object.fromEntries(transformedPackageGlobs),
368
+ }));
369
+ }
370
+ var metadataPath = path_1.default.join(this.includeDirectory, "flamework");
371
+ var metadataExists = fs_1.default.existsSync(metadataPath);
372
+ if (!metadataExists && writtenFiles.size > 0) {
373
+ fs_1.default.mkdirSync(metadataPath);
374
+ }
375
+ try {
376
+ for (var files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
377
+ var file = files_1_1.value;
378
+ var filePath = path_1.default.join(metadataPath, file);
379
+ var contents = writtenFiles.get(file);
380
+ if (contents) {
381
+ fs_1.default.writeFileSync(filePath, contents);
382
+ }
383
+ else if (fs_1.default.existsSync(filePath)) {
384
+ fs_1.default.rmSync(filePath);
385
+ }
386
+ }
387
+ }
388
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
389
+ finally {
390
+ try {
391
+ if (files_1_1 && !files_1_1.done && (_b = files_1.return)) _b.call(files_1);
392
+ }
393
+ finally { if (e_5) throw e_5.error; }
394
+ }
395
+ if (metadataExists && writtenFiles.size === 0) {
396
+ fs_1.default.rmdirSync(metadataPath);
397
+ }
398
+ }
399
+ this.buildInfo.save();
400
+ if (logger_1.Logger.verbose) {
401
+ // Watch mode includes an extra newline when compilation finishes,
402
+ // so we remove that newline before Flamework's message.
403
+ var watch = process.argv.includes("-w") || process.argv.includes("--watch");
404
+ if (watch) {
405
+ process.stdout.write("\x1b[A\x1b[K");
406
+ }
407
+ logger_1.Logger.info("Flamework artifacts finished in ".concat(new Date().getTime() - start, "ms"));
408
+ if (watch) {
409
+ process.stdout.write("\n");
410
+ }
411
+ }
412
+ };
413
+ TransformState.prototype.isUserMacro = function (symbol) {
414
+ var e_6, _a;
415
+ var cached = this.isUserMacroCache.get(symbol);
416
+ if (cached !== undefined)
417
+ return cached;
418
+ if (symbol.declarations) {
419
+ try {
420
+ for (var _b = __values(symbol.declarations), _c = _b.next(); !_c.done; _c = _b.next()) {
421
+ var declaration = _c.value;
422
+ var metadata = nodeMetadata_1.NodeMetadata.fromCache(this, declaration);
423
+ if (metadata.isRequested("macro")) {
424
+ this.isUserMacroCache.set(symbol, true);
425
+ return true;
426
+ }
427
+ }
428
+ }
429
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
430
+ finally {
431
+ try {
432
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
433
+ }
434
+ finally { if (e_6) throw e_6.error; }
435
+ }
436
+ }
437
+ this.isUserMacroCache.set(symbol, false);
438
+ return false;
439
+ };
440
+ TransformState.prototype.addFileImport = function (file, importPath, name) {
441
+ var e_7, _a, e_8, _b;
442
+ var _c;
443
+ // Flamework itself uses features which require imports, this will rewrite those imports to be valid inside the Flamework package.
444
+ if (importPath === packages_1.CORE_PACKAGE && this.packageName === packages_1.CORE_PACKAGE && name === "Reflect") {
445
+ var modulePath = path_1.default.join(this.rootDirectory, "src", "reflect");
446
+ importPath = "./" + path_1.default.relative(path_1.default.dirname(file.fileName), modulePath) || ".";
447
+ }
448
+ var importInfos = this.fileImports.get(file.fileName);
449
+ if (!importInfos)
450
+ this.fileImports.set(file.fileName, (importInfos = []));
451
+ var importInfo = importInfos.find(function (x) { return x.path === importPath; });
452
+ if (!importInfo)
453
+ importInfos.push((importInfo = { path: importPath, entries: [] }));
454
+ var identifier = (_c = importInfo.entries.find(function (x) { return x.name === name; })) === null || _c === void 0 ? void 0 : _c.identifier;
455
+ if (!identifier) {
456
+ try {
457
+ start: for (var _d = __values(file.statements), _e = _d.next(); !_e.done; _e = _d.next()) {
458
+ var statement = _e.value;
459
+ if (!factory_1.f.is.importDeclaration(statement))
460
+ break;
461
+ if (!factory_1.f.is.string(statement.moduleSpecifier))
462
+ continue;
463
+ if (!factory_1.f.is.importClauseDeclaration(statement.importClause))
464
+ continue;
465
+ if (!factory_1.f.is.namedImports(statement.importClause.namedBindings))
466
+ continue;
467
+ if (statement.importClause.isTypeOnly)
468
+ continue;
469
+ if (statement.moduleSpecifier.text !== importPath)
470
+ continue;
471
+ try {
472
+ for (var _f = (e_8 = void 0, __values(statement.importClause.namedBindings.elements)), _g = _f.next(); !_g.done; _g = _f.next()) {
473
+ var importElement = _g.value;
474
+ if (importElement.isTypeOnly) {
475
+ continue;
476
+ }
477
+ if (importElement.propertyName) {
478
+ if (importElement.propertyName.text === name) {
479
+ identifier = importElement.name;
480
+ break start;
481
+ }
482
+ }
483
+ else {
484
+ if (importElement.name.text === name) {
485
+ identifier = importElement.name;
486
+ break start;
487
+ }
488
+ }
489
+ }
490
+ }
491
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
492
+ finally {
493
+ try {
494
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
495
+ }
496
+ finally { if (e_8) throw e_8.error; }
497
+ }
498
+ }
499
+ }
500
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
501
+ finally {
502
+ try {
503
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
504
+ }
505
+ finally { if (e_7) throw e_7.error; }
506
+ }
507
+ }
508
+ if (!identifier) {
509
+ importInfo.entries.push({ name: name, identifier: (identifier = factory_1.f.identifier(name, true)) });
510
+ }
511
+ return identifier;
512
+ };
513
+ TransformState.prototype.getSourceFile = function (node) {
514
+ var parseNode = typescript_1.default.getParseTreeNode(node);
515
+ if (!parseNode)
516
+ throw new Error("Could not find parse tree node");
517
+ return typescript_1.default.getSourceFileOfNode(parseNode);
518
+ };
519
+ TransformState.prototype.getSymbol = function (node, followAlias) {
520
+ if (followAlias === void 0) { followAlias = true; }
521
+ if (factory_1.f.is.namedDeclaration(node)) {
522
+ return this.getSymbol(node.name);
523
+ }
524
+ var symbol = this.typeChecker.getSymbolAtLocation(node);
525
+ if (symbol && followAlias) {
526
+ return typescript_1.default.skipAlias(symbol, this.typeChecker);
527
+ }
528
+ else {
529
+ return symbol;
530
+ }
531
+ };
532
+ TransformState.prototype.hash = function (id, noPrefix) {
533
+ var _a;
534
+ var hashPrefix = this.config.hashPrefix;
535
+ var salt = (_a = this.config.salt) !== null && _a !== void 0 ? _a : this.buildInfo.getSalt();
536
+ var hashGenerator = new hashids_1.default(salt, 2);
537
+ if ((this.isGame && !hashPrefix) || noPrefix) {
538
+ return "".concat(hashGenerator.encode(id));
539
+ }
540
+ else {
541
+ // If the package name is namespaced, then it can be used in
542
+ // other projects so we want to add a prefix to the Id to prevent
543
+ // collisions with other packages or the game.
544
+ return "".concat(hashPrefix !== null && hashPrefix !== void 0 ? hashPrefix : this.packageName, ":").concat(hashGenerator.encode(id));
545
+ }
546
+ };
547
+ TransformState.prototype.obfuscateText = function (text, context) {
548
+ return this.config.obfuscation ? this.buildInfo.hashString(text, context) : text;
549
+ };
550
+ TransformState.prototype.obfuscateArray = function (array) {
551
+ return this.config.obfuscation ? (0, shuffle_1.shuffle)(array) : array;
552
+ };
553
+ TransformState.prototype.addDiagnostic = function (diag) {
554
+ this.context.addDiagnostic(diag);
555
+ };
556
+ TransformState.prototype.capture = function (cb) {
557
+ this.prereqStack.push([]);
558
+ var result = cb();
559
+ return [result, this.prereqStack.pop()];
560
+ };
561
+ TransformState.prototype.prereq = function (statement) {
562
+ var stack = this.prereqStack[this.prereqStack.length - 1];
563
+ if (stack)
564
+ stack.push(statement);
565
+ };
566
+ TransformState.prototype.prereqList = function (statements) {
567
+ var stack = this.prereqStack[this.prereqStack.length - 1];
568
+ if (stack)
569
+ stack.push.apply(stack, __spreadArray([], __read(statements), false));
570
+ };
571
+ TransformState.prototype.isCapturing = function (threshold) {
572
+ if (threshold === void 0) { threshold = 1; }
573
+ return this.prereqStack.length > threshold;
574
+ };
575
+ TransformState.prototype.transform = function (node) {
576
+ var _this = this;
577
+ return typescript_1.default.visitEachChild(node, function (newNode) { return (0, transformNode_1.transformNode)(_this, newNode); }, this.context);
578
+ };
579
+ TransformState.prototype.transformNode = function (node) {
580
+ var _this = this;
581
+ // Technically this isn't guaranteed to return `T`, and TypeScript 5.0+ updated the signature to disallow this,
582
+ // but we don't care so we'll just cast it.
583
+ return typescript_1.default.visitNode(node, function (newNode) { return (0, transformNode_1.transformNode)(_this, newNode); });
584
+ };
585
+ /**
586
+ * Returns the identifier to reach `t` from, for generated guards.
587
+ *
588
+ * Generated guards use functions such as `t.unionList` that older `@rbxts/t` releases lack. When
589
+ * the project resolves a different `@rbxts/t` than `@flamework-experimental/core` does, `t` is imported through
590
+ * core's prelude so that the guards run against the version core was built with.
591
+ */
592
+ TransformState.prototype.getGuardLibrary = function (file) {
593
+ if (this.flameworkGuardLibraryPath) {
594
+ return this.addFileImport(file, this.flameworkGuardLibraryPath, "t");
595
+ }
596
+ // Inside the Flamework packages themselves there is nothing to reconcile.
597
+ if (this.packageName.startsWith("".concat(packages_1.FLAMEWORK_SCOPE, "/"))) {
598
+ this.flameworkGuardLibraryPath = "@rbxts/t";
599
+ return this.addFileImport(file, "@rbxts/t", "t");
600
+ }
601
+ var corePath = (0, tryResolve_1.tryResolveTS)(this, packages_1.CORE_PACKAGE, file.fileName);
602
+ if (corePath === undefined) {
603
+ diagnostics_1.Diagnostics.warning(file.endOfFileToken, "Flamework core was not found, guard generation may not work.");
604
+ return this.addFileImport(file, "@rbxts/t", "t");
605
+ }
606
+ var fileGuardPath = (0, tryResolve_1.tryResolveTS)(this, "@rbxts/t", file.fileName);
607
+ var coreGuardPath = (0, tryResolve_1.tryResolveTS)(this, "@rbxts/t", corePath);
608
+ if (fileGuardPath === coreGuardPath) {
609
+ // @flamework-experimental/core and the consuming project are using the same @rbxts/t version.
610
+ this.flameworkGuardLibraryPath = "@rbxts/t";
611
+ return this.addFileImport(file, "@rbxts/t", "t");
612
+ }
613
+ if (coreGuardPath === undefined ||
614
+ !(0, isPathDescendantOf_1.isPathDescendantOf)(coreGuardPath, path_1.default.join(path_1.default.dirname(corePath), "../node_modules/@rbxts/t"))) {
615
+ diagnostics_1.Diagnostics.warning(file.endOfFileToken, "Valid `@rbxts/t` was not found, guard generation may not work.");
616
+ return this.addFileImport(file, "@rbxts/t", "t");
617
+ }
618
+ this.flameworkGuardLibraryPath = "".concat(packages_1.CORE_PACKAGE, "/out/prelude");
619
+ return this.addFileImport(file, this.flameworkGuardLibraryPath, "t");
620
+ };
621
+ return TransformState;
622
+ }());
623
+ exports.TransformState = TransformState;