discourse/bin/ember-cli
Jarek Radosz d10c1e57e8
DEV: Overhaul typechecking configuration (#35794)
- Switches to typescript 'composite project' mode for improved
organization & performance
- Generates declarations from core modules, and outputs to a new
`@discourse/types` package
- Introduces tsconfigs for core plugins, which leans on that new
`@discourse/types` package
- In future, we plan to publish this discourse-types package for other
themes/plugins to use

The motivation at this stage is primarily to improve editor
autocompletion. We provide absolutely no guarantees about the accuracy
or stability of the generated types.

For now, some issues have been resolved by adding manual `@type`
declarations.

In particular, extensionless imports of `.gjs` files are broken when
running in composite-project mode, so in those cases we have to add
manual `@type {import("./the-file.gjs").default}` declarations.
Unfortunately this failure does not show up in IDEs. We hope to get this
resolved soon.

---------

Co-authored-by: David Taylor <david@taylorhq.com>
Co-authored-by: Chris Manson <chris@manson.ie>
2025-11-12 12:54:34 +00:00

151 lines
3.9 KiB
Ruby
Executable file
Vendored

#!/usr/bin/env ruby
# frozen_string_literal: true
require "pathname"
require "open3"
RAILS_ROOT = File.expand_path("../../", Pathname.new(__FILE__).realpath)
PORT = ENV["UNICORN_PORT"] ||= "3000"
HOSTNAME = ENV["DISCOURSE_HOSTNAME"] ||= "127.0.0.1"
CUSTOM_ARGS = %w[--try --test --build --unicorn -u --forward-host]
PROXY =
if ARGV.include?("--try")
"https://try.discourse.org"
else
"http://#{HOSTNAME}:#{PORT}"
end
def process_running?(pid)
!!Process.kill(0, pid)
rescue Errno::ESRCH
false
end
command =
if ARGV.include?("--test")
"test"
elsif ARGV.include?("--build")
"build"
else
"server"
end
class String
def cyan
"\e[36m#{self}\e[0m"
end
def red
"\033[31m#{self}\e[0m"
end
end
if ARGV.include?("-h") || ARGV.include?("--help")
puts "ember-cli OPTIONS"
puts "#{"--try".cyan} To proxy try.discourse.org"
puts "#{"--test".cyan} To run the test suite"
puts "#{"--unicorn, -u".cyan} To run a unicorn server as well"
puts "The rest of the arguments are passed to ember server per:", ""
exec "pnpm ember #{command} --help"
end
args = ["--dir=frontend/discourse", "ember", command] + (ARGV - CUSTOM_ARGS)
if !args.include?("test") && !args.include?("build") && !args.include?("--proxy")
args << "--proxy"
args << PROXY
end
node_modules_outdated =
begin
File.read("node_modules/.pnpm/lock.yaml") != File.read("pnpm-lock.yaml")
rescue ERRNO::ENOENT
true
end
if node_modules_outdated
puts "[bin/ember-cli] Detected outdated or missing node_modules. Running pnpm install..."
if !system "pnpm", "--dir=#{RAILS_ROOT}", "install"
if !system("command -v pnpm >/dev/null;")
abort "pnpm is not installed. run `npm install -g pnpm`"
end
exit 1
end
end
pnpm_env = {
"TERM" => "dumb", # simple output from ember-cli, so we can parse/forward it more easily
}
pnpm_env["FORWARD_HOST"] = "true" if ARGV.include?("--forward-host")
if ARGV.include?("-u") || ARGV.include?("--unicorn")
unicorn_env = { "DISCOURSE_PORT" => ENV["DISCOURSE_PORT"] || "4200" }
if command == "server" && ENV["CODESPACE_NAME"]
unicorn_env.merge!(
{
"DISCOURSE_PORT" => "443",
"DISCOURSE_FORCE_HTTPS" => "1",
"DISCOURSE_FORCE_HOSTNAME" =>
"#{ENV["CODESPACE_NAME"]}-4200.#{ENV["GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"]}",
},
)
end
unicorn_pid = spawn(unicorn_env, __dir__ + "/unicorn")
ember_cli_pid = nil
tsc_pid = nil
Thread.new do
Open3.popen2e(pnpm_env, "pnpm", *args.to_a.flatten) do |i, oe, t|
ember_cli_pid = t.pid
puts "Ember CLI running on PID: #{ember_cli_pid}"
oe.each do |line|
if line.include?("\e[32m200\e") || line.include?("\e[36m304\e[0m") ||
line.include?("POST /message-bus")
# skip 200s and 304s and message bus
else
puts "[ember-cli] #{line}"
end
end
end
if process_running?(unicorn_pid)
puts "[bin/ember-cli] ember-cli process stopped. Terminating unicorn."
Process.kill("TERM", unicorn_pid)
end
end
Thread.new do
Open3.popen2e(pnpm_env, "pnpm", "ember-tsc", "-b", "--watch", "--preserveWatchOutput") do |i, oe, t|
tsc_pid = t.pid
puts "Ember TSC running on PID: #{tsc_pid}"
oe.each do |line|
puts "[ember-tsc] #{line}"
end
end
if process_running?(unicorn_pid)
puts "[bin/ember-cli] ember-tsc process stopped. Terminating unicorn."
Process.kill("TERM", unicorn_pid)
end
end
trap("SIGINT") do
# we got to swallow sigint to give time for
# children to handle it
end
Process.wait(unicorn_pid)
if ember_cli_pid && process_running?(ember_cli_pid)
puts "[bin/ember-cli] unicorn process stopped. Terminating ember-cli."
Process.kill("TERM", ember_cli_pid)
end
if tsc_pid && process_running?(tsc_pid)
puts "[bin/ember-cli] unicorn process stopped. Terminating ember-tsc."
Process.kill("TERM", tsc_pid)
end
else
exec(pnpm_env, "pnpm", *args.to_a.flatten)
end