@trioforge/crucible 0.2.0 → 0.3.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.
@@ -340,6 +340,26 @@ module.exports = function transformer(program, config = {}, extras = {}) {
340
340
  call(runtime("defineClass"), [f.createIdentifier(node.name.text), object(data)]),
341
341
  );
342
342
  };
343
+ // A Rojo project may map a folder's files one by one rather than the folder, as Rogen does before their
344
+ // outputs exist. Each such file names the instance of the folder that holds it.
345
+ const mappedByFiles = (resolver, folder, out) => {
346
+ const found = new Set();
347
+ for (const source of program.getSourceFiles()) {
348
+ const parts = path
349
+ .relative(folder, source.fileName)
350
+ .replace(/\.tsx?$/, "")
351
+ .split(path.sep);
352
+ const name = parts.at(-1).replace(/\.(server|client)$/, "");
353
+ if (source.isDeclarationFile || parts[0] === ".." || path.isAbsolute(parts[0]) || name === "index")
354
+ continue;
355
+ const rbx = resolver.getRbxPathFromFilePath(path.join(out, ...parts) + ".luau");
356
+ const tail = [...parts.slice(0, -1), name];
357
+ if (rbx?.length > tail.length && tail.every((part, at) => rbx.at(at - tail.length) === part))
358
+ found.add(rbx.slice(0, -tail.length).join("\0"));
359
+ }
360
+ if (found.size > 1) return null;
361
+ return found.size ? [...found][0].split("\0") : undefined;
362
+ };
343
363
  const boot = (node) => {
344
364
  let options = node.arguments[0];
345
365
  while (
@@ -374,10 +394,10 @@ module.exports = function transformer(program, config = {}, extras = {}) {
374
394
  report(entry, "CRU006", "load entry must be a string literal.");
375
395
  return entry;
376
396
  }
377
- const root = path.dirname(
397
+ const configFile =
378
398
  program.getCompilerOptions().configFilePath ??
379
- path.join(program.getCurrentDirectory(), "tsconfig.json"),
380
- );
399
+ path.join(program.getCurrentDirectory(), "tsconfig.json");
400
+ const root = packageOf(configFile)?.dir ?? path.dirname(configFile);
381
401
  let resolver;
382
402
  try {
383
403
  const compiler =
@@ -385,8 +405,10 @@ module.exports = function transformer(program, config = {}, extras = {}) {
385
405
  /roblox-ts[\\/]out[\\/]Project[\\/]functions[\\/]compileFiles\.js$/.test(file),
386
406
  ) ?? require.resolve("roblox-ts/package.json", { paths: [root, __dirname] });
387
407
  const { RojoResolver } = createRequire(compiler)("@roblox-ts/rojo-resolver");
388
- const rojoPath = config.rojo ?? RojoResolver.findRojoConfigFilePath(root).path;
389
- resolver = rojoPath && RojoResolver.fromPath(path.resolve(root, rojoPath));
408
+ const rojoPath = config.rojo
409
+ ? path.resolve(root, config.rojo)
410
+ : RojoResolver.findRojoConfigFilePath(path.dirname(configFile)).path;
411
+ resolver = rojoPath && RojoResolver.fromPath(rojoPath);
390
412
  } catch {
391
413
  report(entry, "CRU006", "Cannot load the running compiler's Rojo resolver or project mapping.");
392
414
  return entry;
@@ -399,12 +421,18 @@ module.exports = function transformer(program, config = {}, extras = {}) {
399
421
  const suffix = entry.text.slice(prefix.length).replace(/\.tsx?$/, "");
400
422
  const opts = program.getCompilerOptions();
401
423
  const inputRoot = sourceRoot(opts, [program.getCommonSourceDirectory()]);
402
- const relative = inputRoot && path.relative(inputRoot, path.resolve(root, prefix));
424
+ const folder = path.resolve(root, prefix);
425
+ const relative = inputRoot && path.relative(inputRoot, folder);
426
+ const inside = relative !== undefined && !relative.startsWith("..") && !path.isAbsolute(relative);
427
+ const out = inside && path.resolve(opts.outDir, relative);
403
428
  const mapped =
404
- relative !== undefined &&
405
- !relative.startsWith("..") &&
406
- !path.isAbsolute(relative) &&
407
- resolver?.getRbxPathFromFilePath(path.resolve(opts.outDir, relative));
429
+ out &&
430
+ resolver &&
431
+ (resolver.getRbxPathFromFilePath(out) ?? mappedByFiles(resolver, folder, out));
432
+ if (mapped === null) {
433
+ report(entry, "CRU006", "load prefix maps to more than one Rojo folder.");
434
+ return entry;
435
+ }
408
436
  if (!mapped) {
409
437
  report(entry, "CRU006", "load prefix is outside the Rojo mapping.");
410
438
  return entry;
@@ -531,9 +559,19 @@ module.exports = function transformer(program, config = {}, extras = {}) {
531
559
  specifier &&
532
560
  ts.isStringLiteral(specifier) &&
533
561
  specifier.text.startsWith("@trioforge/crucible/") &&
534
- !["@trioforge/crucible/server", "@trioforge/crucible/client"].includes(specifier.text)
562
+ ![
563
+ "@trioforge/crucible/server",
564
+ "@trioforge/crucible/client",
565
+ "@trioforge/crucible/vide",
566
+ "@trioforge/crucible/util/random",
567
+ "@trioforge/crucible/maths/spline",
568
+ ].includes(specifier.text)
535
569
  )
536
- report(node, "CRU004", "Import only the root, server or client Crucible entries.");
570
+ report(
571
+ node,
572
+ "CRU004",
573
+ "Import only the root, server, client, vide, util/random or maths/spline Crucible entries.",
574
+ );
537
575
  }
538
576
  if (ts.isClassExpression(node) || ts.isClassDeclaration(node)) {
539
577
  const type = instanceType(node);
@@ -0,0 +1,4 @@
1
+ {
2
+ "main": "../../out/util/random/init.luau",
3
+ "types": "../../out/util/random/index.d.ts"
4
+ }