@dreamboard-games/cli 0.1.30-alpha.0 → 0.1.30-alpha.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/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  CONFIG_FLAG_ARGS,
4
4
  IS_PUBLISHED_BUILD,
5
5
  LOCAL_REGISTRY_URL,
6
+ PUBLISHED_ENVIRONMENT,
6
7
  REDUCER_TESTING_TYPES_WRAPPER_CONTENT,
7
8
  STALE_CONTRACT_ARTIFACT_CODE,
8
9
  STALE_CONTRACT_ARTIFACT_EXIT_CODE,
@@ -59,6 +60,7 @@ import {
59
60
  materializeManifestTable,
60
61
  materializeSourceChangeOperations,
61
62
  normalizeSlug,
63
+ parseAuthCommandArgs,
62
64
  parseCloneCommandArgs,
63
65
  parseCompileCommandArgs,
64
66
  parseConfigCommandArgs,
@@ -70,10 +72,12 @@ import {
70
72
  parsePlayerCountFlags,
71
73
  parsePositiveInt,
72
74
  parsePullCommandArgs,
75
+ parseQueryCommandArgs,
73
76
  parseStatusCommandArgs,
74
77
  parseSyncCommandArgs,
75
78
  perPlayerSchema,
76
79
  projectIdFromSessionGameSource,
80
+ queryWorkshopRulebook,
77
81
  queueProjectRevisionCompileSdk,
78
82
  refreshResolvedAuthSession,
79
83
  removeExtraneousFiles,
@@ -101,7 +105,7 @@ import {
101
105
  writeSnapshot,
102
106
  writeSnapshotFromFiles,
103
107
  writeSourceFiles
104
- } from "./chunk-3XNJT3RK.js";
108
+ } from "./chunk-RS7UXJZV.js";
105
109
  import {
106
110
  DEFAULT_LOGIN_TIMEOUT_MS,
107
111
  DEFAULT_WEB_BASE_URL,
@@ -113,6 +117,7 @@ import {
113
117
  clearCredentials,
114
118
  ensureDir,
115
119
  exists,
120
+ getActiveCredentialBackendName,
116
121
  getGlobalAuthPath,
117
122
  getGlobalConfigPath,
118
123
  getStoredSession,
@@ -125,10 +130,13 @@ import {
125
130
  setCredentials,
126
131
  writeJsonFile,
127
132
  writeTextFile
128
- } from "./chunk-TSJVWTJO.js";
133
+ } from "./chunk-C6UAT6EH.js";
129
134
  import "./chunk-7FOO4AJI.js";
130
135
  import "./chunk-2H7UOFLK.js";
131
136
 
137
+ // src/commands/auth.ts
138
+ import crypto from "crypto";
139
+
132
140
  // ../../node_modules/.pnpm/citty@0.2.2/node_modules/citty/dist/_chunks/libs/scule.mjs
133
141
  var NUMBER_CHAR_RE = /\d/;
134
142
  var STR_SPLITTERS = [
@@ -1697,6 +1705,505 @@ function _getDefaultLogLevel() {
1697
1705
  }
1698
1706
  var consola = createConsola2();
1699
1707
 
1708
+ // src/auth/auth-server.ts
1709
+ import {
1710
+ createServer
1711
+ } from "http";
1712
+ import { spawn } from "child_process";
1713
+ var DEFAULT_OAUTH_CALLBACK_PORT = 49371;
1714
+ async function startOAuthCallbackServer(state, timeoutMs) {
1715
+ let resolveCode;
1716
+ let rejectCode;
1717
+ const waitForCode = new Promise((resolve, reject) => {
1718
+ resolveCode = resolve;
1719
+ rejectCode = reject;
1720
+ });
1721
+ const portCandidate = resolveOAuthCallbackPort();
1722
+ const server = createServer(
1723
+ async (request, response) => {
1724
+ try {
1725
+ const requestUrl = new URL(request.url ?? "/", "http://127.0.0.1");
1726
+ if (request.method === "GET" && requestUrl.pathname === "/oauth/callback") {
1727
+ const receivedState = requestUrl.searchParams.get("state");
1728
+ const code = requestUrl.searchParams.get("code");
1729
+ const error = requestUrl.searchParams.get("error");
1730
+ if (error) {
1731
+ throw new Error(`Clerk OAuth returned ${error}.`);
1732
+ }
1733
+ if (!code || receivedState !== state) {
1734
+ writeCorsResponse(request, response, 400, "Invalid OAuth callback");
1735
+ return;
1736
+ }
1737
+ resolveCode({ code });
1738
+ response.once("finish", () => server.close());
1739
+ writeHtmlResponse(
1740
+ response,
1741
+ 200,
1742
+ "Dreamboard CLI login complete. You can return to your terminal."
1743
+ );
1744
+ return;
1745
+ }
1746
+ writeHtmlResponse(
1747
+ response,
1748
+ 200,
1749
+ "Dreamboard CLI OAuth callback server"
1750
+ );
1751
+ } catch (error) {
1752
+ rejectCode(
1753
+ error instanceof Error ? error : new Error("Failed to handle OAuth callback.")
1754
+ );
1755
+ writeHtmlResponse(response, 500, "Dreamboard CLI login failed.");
1756
+ }
1757
+ }
1758
+ );
1759
+ try {
1760
+ await new Promise((resolve, reject) => {
1761
+ server.once("error", reject);
1762
+ server.listen(portCandidate, "127.0.0.1", () => {
1763
+ server.off("error", reject);
1764
+ resolve();
1765
+ });
1766
+ });
1767
+ } catch (error) {
1768
+ const portError = error instanceof Error ? error : new Error("Failed to start OAuth callback server");
1769
+ const configuredByEnv = Boolean(
1770
+ process.env.DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT
1771
+ );
1772
+ const message = configuredByEnv ? `Failed to start OAuth callback server on configured port ${portCandidate}.` : `Failed to start OAuth callback server on port ${portCandidate}. Register this loopback redirect URI with Clerk and keep the port available, or set DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT.`;
1773
+ const wrapped = new Error(`${message} ${portError.message}`);
1774
+ server.close();
1775
+ rejectCode(wrapped);
1776
+ throw wrapped;
1777
+ }
1778
+ if (!server.listening) {
1779
+ const error = new Error("Failed to start OAuth callback server.");
1780
+ rejectCode(error);
1781
+ throw error;
1782
+ }
1783
+ const timer = setTimeout(() => {
1784
+ rejectCode(new Error("Login timed out."));
1785
+ server?.close();
1786
+ }, timeoutMs);
1787
+ waitForCode.finally(() => clearTimeout(timer));
1788
+ const port = portCandidateFromServer(server);
1789
+ return {
1790
+ port,
1791
+ redirectUri: `http://127.0.0.1:${port}/oauth/callback`,
1792
+ waitForCode,
1793
+ close: () => server?.close()
1794
+ };
1795
+ }
1796
+ function resolveOAuthCallbackPort() {
1797
+ const rawPort = process.env.DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT?.trim();
1798
+ if (!rawPort) {
1799
+ return DEFAULT_OAUTH_CALLBACK_PORT;
1800
+ }
1801
+ const port = Number(rawPort);
1802
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
1803
+ throw new Error(
1804
+ `Invalid DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT '${rawPort}'. Expected a TCP port from 1 to 65535.`
1805
+ );
1806
+ }
1807
+ return port;
1808
+ }
1809
+ function portCandidateFromServer(server) {
1810
+ const address = server.address();
1811
+ if (!address || typeof address === "string") {
1812
+ throw new Error("Auth callback server did not expose a bound port.");
1813
+ }
1814
+ return address.port;
1815
+ }
1816
+ function writeCorsResponse(request, response, statusCode, body) {
1817
+ const origin = request.headers.origin ?? "*";
1818
+ response.writeHead(statusCode, {
1819
+ "Access-Control-Allow-Origin": origin,
1820
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
1821
+ "Access-Control-Allow-Headers": "Content-Type",
1822
+ "Content-Type": "text/plain; charset=utf-8"
1823
+ });
1824
+ response.end(body);
1825
+ }
1826
+ function writeHtmlResponse(response, statusCode, body) {
1827
+ response.writeHead(statusCode, {
1828
+ "Content-Type": "text/html; charset=utf-8"
1829
+ });
1830
+ response.end(
1831
+ `<!doctype html><meta charset="utf-8"><title>Dreamboard CLI</title><p>${escapeHtml(body)}</p>`
1832
+ );
1833
+ }
1834
+ function escapeHtml(value) {
1835
+ return value.replace(/[&<>"']/g, (char) => {
1836
+ switch (char) {
1837
+ case "&":
1838
+ return "&amp;";
1839
+ case "<":
1840
+ return "&lt;";
1841
+ case ">":
1842
+ return "&gt;";
1843
+ case '"':
1844
+ return "&quot;";
1845
+ default:
1846
+ return "&#39;";
1847
+ }
1848
+ });
1849
+ }
1850
+ function openBrowser(url) {
1851
+ const platform2 = process.platform;
1852
+ let command;
1853
+ if (platform2 === "darwin") {
1854
+ command = ["open", url];
1855
+ } else if (platform2 === "win32") {
1856
+ command = ["cmd", "/c", "start", "", url];
1857
+ } else {
1858
+ command = ["xdg-open", url];
1859
+ }
1860
+ const [commandName, ...commandArgs] = command;
1861
+ const child = spawn(commandName, commandArgs, {
1862
+ stdio: "ignore",
1863
+ detached: true
1864
+ });
1865
+ child.unref();
1866
+ }
1867
+
1868
+ // src/commands/auth.ts
1869
+ async function loginWithBrowser(config, quiet) {
1870
+ const state = crypto.randomUUID();
1871
+ const pkce = createPkcePair();
1872
+ const server = await startOAuthCallbackServer(
1873
+ state,
1874
+ DEFAULT_LOGIN_TIMEOUT_MS
1875
+ );
1876
+ const loginUrl = buildClerkAuthorizationUrl({
1877
+ config: {
1878
+ issuer: config.clerkOAuthIssuer,
1879
+ clientId: config.clerkOAuthClientId,
1880
+ tokenUrl: config.clerkOAuthTokenUrl,
1881
+ scope: config.clerkOAuthScope
1882
+ },
1883
+ redirectUri: server.redirectUri,
1884
+ state,
1885
+ codeChallenge: pkce.challenge
1886
+ }).toString();
1887
+ if (!quiet) {
1888
+ consola.info("Opening browser for login...");
1889
+ consola.info(`If the browser does not open, visit: ${loginUrl}`);
1890
+ }
1891
+ openBrowser(loginUrl);
1892
+ if (!quiet) {
1893
+ consola.start("Waiting for login to complete...");
1894
+ }
1895
+ try {
1896
+ const { code } = await server.waitForCode;
1897
+ const tokenResponse = await exchangeClerkOAuthCode({
1898
+ config: {
1899
+ issuer: config.clerkOAuthIssuer,
1900
+ clientId: config.clerkOAuthClientId,
1901
+ tokenUrl: config.clerkOAuthTokenUrl
1902
+ },
1903
+ code,
1904
+ redirectUri: server.redirectUri,
1905
+ codeVerifier: pkce.verifier
1906
+ });
1907
+ return {
1908
+ token: tokenResponse.accessToken,
1909
+ refreshToken: tokenResponse.refreshToken,
1910
+ expiresAt: tokenResponse.expiresAt,
1911
+ tokenUrl: tokenResponse.tokenUrl
1912
+ };
1913
+ } finally {
1914
+ server.close();
1915
+ }
1916
+ }
1917
+ var auth_default = defineCommand({
1918
+ meta: { name: "auth", description: "Manage stored Dreamboard sessions" },
1919
+ args: {
1920
+ action: {
1921
+ type: "positional",
1922
+ description: IS_PUBLISHED_BUILD ? "Action: clear | login" : "Action: set | clear | login | env | status",
1923
+ required: true
1924
+ },
1925
+ ...IS_PUBLISHED_BUILD ? {} : {
1926
+ tokenValue: {
1927
+ type: "positional",
1928
+ description: "Token value (for set) or environment name (for env)",
1929
+ required: false
1930
+ },
1931
+ token: {
1932
+ type: "string",
1933
+ description: "Auth token (alternative)"
1934
+ },
1935
+ jwt: {
1936
+ type: "boolean",
1937
+ description: "Print auth token JSON to stdout"
1938
+ },
1939
+ env: {
1940
+ type: "string",
1941
+ description: "Environment: local | staging | prod"
1942
+ }
1943
+ }
1944
+ },
1945
+ async run({ args }) {
1946
+ const parsedArgs = parseAuthCommandArgs(args);
1947
+ const action = parsedArgs.action;
1948
+ const globalConfig = await loadGlobalConfig();
1949
+ if (IS_PUBLISHED_BUILD && action !== "login" && action !== "clear") {
1950
+ throw new Error(
1951
+ "The published Dreamboard CLI only supports browser login and logout. Use `dreamboard login` or `dreamboard logout`."
1952
+ );
1953
+ }
1954
+ if (action === "env") {
1955
+ if (IS_PUBLISHED_BUILD) {
1956
+ throw new Error(
1957
+ "The published Dreamboard CLI is production-only and does not support switching environments."
1958
+ );
1959
+ }
1960
+ const environment = parsedArgs.tokenValue ?? parsedArgs.env;
1961
+ if (!environment) {
1962
+ throw new Error("Usage: dreamboard auth env <local|staging|prod>");
1963
+ }
1964
+ if (!["local", "staging", "prod"].includes(environment)) {
1965
+ throw new Error(
1966
+ `Invalid environment '${environment}'. Valid options: local, staging, prod`
1967
+ );
1968
+ }
1969
+ await saveGlobalConfig({
1970
+ ...globalConfig,
1971
+ environment
1972
+ });
1973
+ consola.success(`Environment set to '${environment}'.`);
1974
+ return;
1975
+ }
1976
+ if (action === "set") {
1977
+ if (IS_PUBLISHED_BUILD) {
1978
+ throw new Error(
1979
+ "Direct JWT injection is not supported in the published Dreamboard CLI. Use `dreamboard login` so the CLI can store a refreshable session."
1980
+ );
1981
+ }
1982
+ const token = parsedArgs.tokenValue ?? parsedArgs.token ?? "";
1983
+ if (!token) throw new Error("Usage: dreamboard auth set <token>");
1984
+ await setAccessOnlySession(token);
1985
+ consola.success(`Auth token saved to ${getGlobalAuthPath()}.`);
1986
+ return;
1987
+ }
1988
+ if (action === "clear") {
1989
+ await clearCredentials();
1990
+ consola.success(
1991
+ `Stored Dreamboard session cleared from ${getGlobalAuthPath()}.`
1992
+ );
1993
+ return;
1994
+ }
1995
+ if (action === "login") {
1996
+ const shouldPrintJwt = !IS_PUBLISHED_BUILD && parsedArgs.jwt === true;
1997
+ const environment = IS_PUBLISHED_BUILD ? PUBLISHED_ENVIRONMENT : parsedArgs.env || globalConfig.environment || "staging";
1998
+ const storedSession = await getStoredSession();
1999
+ let accessToken = storedSession?.accessToken;
2000
+ let refreshToken = storedSession?.refreshToken;
2001
+ let tokenExpiresAt = storedSession?.tokenExpiresAt;
2002
+ let clerkOAuthTokenUrl = storedSession?.clerkOAuthTokenUrl;
2003
+ let didRefreshStoredSession = false;
2004
+ let didUseBrowserLogin = false;
2005
+ const resolvedConfig = resolveConfig(
2006
+ globalConfig,
2007
+ { env: environment },
2008
+ void 0,
2009
+ storedSession
2010
+ );
2011
+ if (accessToken && refreshToken) {
2012
+ try {
2013
+ const refreshed = await refreshResolvedAuthSession(resolvedConfig);
2014
+ accessToken = refreshed?.accessToken ?? accessToken;
2015
+ refreshToken = refreshed?.refreshToken ?? refreshToken;
2016
+ tokenExpiresAt = refreshed?.tokenExpiresAt ?? tokenExpiresAt;
2017
+ clerkOAuthTokenUrl = refreshed?.clerkOAuthTokenUrl ?? clerkOAuthTokenUrl;
2018
+ didRefreshStoredSession = Boolean(refreshed);
2019
+ } catch (error) {
2020
+ consola.warn(
2021
+ error instanceof Error ? error.message : "Stored Dreamboard CLI session refresh failed."
2022
+ );
2023
+ accessToken = void 0;
2024
+ refreshToken = void 0;
2025
+ }
2026
+ }
2027
+ if (!accessToken) {
2028
+ const browserLogin = await loginWithBrowser(
2029
+ resolvedConfig,
2030
+ shouldPrintJwt
2031
+ );
2032
+ accessToken = browserLogin.token;
2033
+ refreshToken = browserLogin.refreshToken;
2034
+ tokenExpiresAt = browserLogin.expiresAt;
2035
+ clerkOAuthTokenUrl = browserLogin.tokenUrl;
2036
+ didUseBrowserLogin = true;
2037
+ }
2038
+ if (!accessToken) {
2039
+ throw new Error("Login completed but no access token was returned.");
2040
+ }
2041
+ await saveGlobalConfig({
2042
+ ...globalConfig,
2043
+ environment
2044
+ });
2045
+ if (refreshToken) {
2046
+ await setCredentials({
2047
+ accessToken,
2048
+ refreshToken,
2049
+ tokenExpiresAt,
2050
+ clerkOAuthIssuer: resolvedConfig.clerkOAuthIssuer,
2051
+ clerkOAuthClientId: resolvedConfig.clerkOAuthClientId,
2052
+ clerkOAuthTokenUrl,
2053
+ environment
2054
+ });
2055
+ } else {
2056
+ await setAccessOnlySession(accessToken);
2057
+ }
2058
+ if (shouldPrintJwt) {
2059
+ process.stdout.write(
2060
+ `${JSON.stringify(
2061
+ {
2062
+ token: accessToken,
2063
+ refreshToken: refreshToken ?? null,
2064
+ environment
2065
+ },
2066
+ null,
2067
+ 2
2068
+ )}
2069
+ `
2070
+ );
2071
+ return;
2072
+ }
2073
+ if (didUseBrowserLogin) {
2074
+ consola.success(
2075
+ `Browser login successful. Session saved to ${getGlobalAuthPath()}`
2076
+ );
2077
+ } else if (storedSession?.accessToken && didRefreshStoredSession) {
2078
+ consola.success(
2079
+ `Stored auth session refreshed and saved to ${getGlobalAuthPath()}`
2080
+ );
2081
+ } else if (storedSession?.accessToken) {
2082
+ consola.success(
2083
+ `Stored auth token found. Session data remains in ${getGlobalAuthPath()}`
2084
+ );
2085
+ }
2086
+ return;
2087
+ }
2088
+ if (action === "status") {
2089
+ const storedSession = await getStoredSession();
2090
+ const resolvedConfig = resolveConfig(
2091
+ globalConfig,
2092
+ { env: parsedArgs.env },
2093
+ void 0,
2094
+ storedSession
2095
+ );
2096
+ const environment = parsedArgs.env || globalConfig.environment || "staging";
2097
+ const authTokenExpiry = getAuthTokenExpiry(resolvedConfig.authToken);
2098
+ const backendName = await getActiveCredentialBackendName();
2099
+ consola.log(`Environment: ${environment}`);
2100
+ consola.log(`Auth token source: ${resolvedConfig.authTokenSource}`);
2101
+ consola.log(`Refresh token source: ${resolvedConfig.refreshTokenSource}`);
2102
+ consola.log(
2103
+ `Credential backend: ${backendName}${backendName === "keychain" ? " (OS keychain via @napi-rs/keyring)" : ` (${getGlobalAuthPath()})`}`
2104
+ );
2105
+ const preference = globalConfig.credentialBackend;
2106
+ if (preference) {
2107
+ consola.log(`Credential backend preference (config): ${preference}`);
2108
+ } else {
2109
+ consola.log(
2110
+ 'Credential backend preference (config): file (default; set `"credentialBackend": "keychain"` in config.json to opt in)'
2111
+ );
2112
+ }
2113
+ if (process.env.DREAMBOARD_CREDENTIAL_BACKEND) {
2114
+ consola.log(
2115
+ `Backend override: DREAMBOARD_CREDENTIAL_BACKEND=${process.env.DREAMBOARD_CREDENTIAL_BACKEND}`
2116
+ );
2117
+ }
2118
+ consola.log(`Config path: ${getGlobalConfigPath()}`);
2119
+ if (!resolvedConfig.authToken) {
2120
+ consola.warn("No Dreamboard session found.");
2121
+ return;
2122
+ }
2123
+ if (authTokenExpiry) {
2124
+ const isExpired = authTokenExpiry.getTime() <= Date.now();
2125
+ consola.log(
2126
+ `Access token expires at: ${authTokenExpiry.toISOString()} (${isExpired ? "expired" : "active"})`
2127
+ );
2128
+ if (isExpired) {
2129
+ if (!resolvedConfig.refreshToken) {
2130
+ consola.warn(
2131
+ "Access token is expired and no refresh token is available. Run `dreamboard login` to authenticate again."
2132
+ );
2133
+ return;
2134
+ }
2135
+ const refreshed = await refreshResolvedAuthSession(resolvedConfig);
2136
+ if (!refreshed?.accessToken) {
2137
+ consola.warn(
2138
+ "Access token is expired and refresh did not return a new session."
2139
+ );
2140
+ return;
2141
+ }
2142
+ const refreshedExpiry = getAuthTokenExpiry(refreshed.accessToken);
2143
+ consola.success("Access token was expired and has been refreshed.");
2144
+ if (refreshedExpiry) {
2145
+ consola.log(
2146
+ `Refreshed access token expires at: ${refreshedExpiry.toISOString()}`
2147
+ );
2148
+ }
2149
+ return;
2150
+ }
2151
+ } else {
2152
+ consola.log("Access token expiry: unavailable");
2153
+ }
2154
+ consola.success("Dreamboard session is active.");
2155
+ return;
2156
+ }
2157
+ throw new Error(
2158
+ IS_PUBLISHED_BUILD ? "Usage:\n dreamboard auth clear\n dreamboard auth login" : "Usage:\n dreamboard auth clear\n dreamboard auth login [--env <local|staging|prod>] [--jwt]\n dreamboard auth set <token>\n dreamboard auth env <local|staging|prod>\n dreamboard auth status [--env <local|staging|prod>]"
2159
+ );
2160
+ }
2161
+ });
2162
+
2163
+ // src/commands/query.ts
2164
+ var query_default = defineCommand({
2165
+ meta: {
2166
+ name: "query",
2167
+ description: "Query rulebook text by title"
2168
+ },
2169
+ args: {
2170
+ title: {
2171
+ type: "positional",
2172
+ description: "Board game title to search in the rulebook library",
2173
+ required: true
2174
+ },
2175
+ ...CONFIG_FLAG_ARGS
2176
+ },
2177
+ async run({ args }) {
2178
+ const parsedArgs = parseQueryCommandArgs(args);
2179
+ const [globalConfig, storedSession] = await Promise.all([
2180
+ loadGlobalConfig(),
2181
+ getStoredSession()
2182
+ ]);
2183
+ const config = resolveConfig(
2184
+ globalConfig,
2185
+ parsedArgs,
2186
+ void 0,
2187
+ storedSession
2188
+ );
2189
+ requireAuth(config);
2190
+ await configureClient(config);
2191
+ const { data, error, response } = await queryWorkshopRulebook({
2192
+ query: {
2193
+ title: parsedArgs.title
2194
+ }
2195
+ });
2196
+ if (!data) {
2197
+ throw toDreamboardApiError(
2198
+ error,
2199
+ response,
2200
+ `Failed to query rulebook for '${parsedArgs.title}'`
2201
+ );
2202
+ }
2203
+ console.log(data.ruleText);
2204
+ }
2205
+ });
2206
+
1700
2207
  // src/commands/clone.ts
1701
2208
  import path5 from "path";
1702
2209
 
@@ -2406,8 +2913,8 @@ import { unlink as unlink2 } from "fs/promises";
2406
2913
  import path3 from "path";
2407
2914
 
2408
2915
  // src/services/project/workspace-dependencies.ts
2409
- import crypto from "crypto";
2410
- import { spawn } from "child_process";
2916
+ import crypto2 from "crypto";
2917
+ import { spawn as spawn2 } from "child_process";
2411
2918
  import "events";
2412
2919
  import { existsSync as existsSync2 } from "fs";
2413
2920
  import { mkdir, lstat, readFile as readFile2, rm as rm2, writeFile } from "fs/promises";
@@ -2666,7 +3173,7 @@ async function readRepoPackageManager() {
2666
3173
  return hasExactPnpmVersion(packageManager) ? packageManager : DEFAULT_PACKAGE_MANAGER;
2667
3174
  }
2668
3175
  function fingerprintContent(parts) {
2669
- return crypto.createHash("sha256").update(parts.join("\n---\n")).digest("hex");
3176
+ return crypto2.createHash("sha256").update(parts.join("\n---\n")).digest("hex");
2670
3177
  }
2671
3178
  function resolvePnpmInstallInvocation(installArgs) {
2672
3179
  const corepackPath = path2.join(path2.dirname(process.execPath), "corepack");
@@ -2684,7 +3191,7 @@ async function runPackageManagerCommand(projectRoot, command) {
2684
3191
  }
2685
3192
  async function runLockfileCommand(projectRoot, command) {
2686
3193
  await new Promise((resolve, reject) => {
2687
- const child = spawn(command.binary, command.args, {
3194
+ const child = spawn2(command.binary, command.args, {
2688
3195
  cwd: projectRoot,
2689
3196
  env: process.env,
2690
3197
  stdio: ["ignore", "pipe", "pipe"]
@@ -3003,7 +3510,7 @@ function buildRemoteAlignedSnapshotFiles(options) {
3003
3510
  }
3004
3511
 
3005
3512
  // src/services/project/local-maintainer-registry.ts
3006
- import { spawn as spawn2 } from "child_process";
3513
+ import { spawn as spawn3 } from "child_process";
3007
3514
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
3008
3515
  import path4 from "path";
3009
3516
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -3122,7 +3629,7 @@ function parseJsonPayload(output) {
3122
3629
  async function runLocalMaintainerScript(args) {
3123
3630
  const invocation = getScriptInvocation();
3124
3631
  return new Promise((resolve, reject) => {
3125
- const child = spawn2(invocation.command, [...invocation.args, ...args], {
3632
+ const child = spawn3(invocation.command, [...invocation.args, ...args], {
3126
3633
  cwd: invocation.cwd,
3127
3634
  stdio: ["ignore", "pipe", "pipe"],
3128
3635
  env: process.env
@@ -3458,7 +3965,7 @@ async function readDreamboardRegistryFromNpmrc(projectRoot) {
3458
3965
  }
3459
3966
 
3460
3967
  // src/services/project/local-typecheck.ts
3461
- import { spawn as spawn3 } from "child_process";
3968
+ import { spawn as spawn4 } from "child_process";
3462
3969
  import { lstat as lstat2 } from "fs/promises";
3463
3970
  import { createRequire } from "module";
3464
3971
  import path7 from "path";
@@ -3512,7 +4019,7 @@ async function resolveTypecheckRunner(projectRoot) {
3512
4019
  };
3513
4020
  }
3514
4021
  const globalTscAvailable = await new Promise((resolve) => {
3515
- const child = spawn3("tsc", ["--version"], {
4022
+ const child = spawn4("tsc", ["--version"], {
3516
4023
  env: process.env,
3517
4024
  stdio: "ignore"
3518
4025
  });
@@ -3533,7 +4040,7 @@ async function resolveTypecheckRunner(projectRoot) {
3533
4040
  }
3534
4041
  async function runTypecheckProject(runner, projectRoot, projectPath) {
3535
4042
  return new Promise((resolve, reject) => {
3536
- const child = spawn3(
4043
+ const child = spawn4(
3537
4044
  runner.command,
3538
4045
  [...runner.argsPrefix, "--noEmit", "-p", projectPath],
3539
4046
  {
@@ -4052,166 +4559,6 @@ async function resolvePlayerCount(projectRoot, flags) {
4052
4559
  return Math.max(1, Math.floor(minPlayers));
4053
4560
  }
4054
4561
 
4055
- // src/auth/auth-server.ts
4056
- import {
4057
- createServer
4058
- } from "http";
4059
- import { spawn as spawn4 } from "child_process";
4060
- var DEFAULT_OAUTH_CALLBACK_PORT = 49371;
4061
- async function startOAuthCallbackServer(state, timeoutMs) {
4062
- let resolveCode;
4063
- let rejectCode;
4064
- const waitForCode = new Promise((resolve, reject) => {
4065
- resolveCode = resolve;
4066
- rejectCode = reject;
4067
- });
4068
- const portCandidate = resolveOAuthCallbackPort();
4069
- const server = createServer(
4070
- async (request, response) => {
4071
- try {
4072
- const requestUrl = new URL(request.url ?? "/", "http://127.0.0.1");
4073
- if (request.method === "GET" && requestUrl.pathname === "/oauth/callback") {
4074
- const receivedState = requestUrl.searchParams.get("state");
4075
- const code = requestUrl.searchParams.get("code");
4076
- const error = requestUrl.searchParams.get("error");
4077
- if (error) {
4078
- throw new Error(`Clerk OAuth returned ${error}.`);
4079
- }
4080
- if (!code || receivedState !== state) {
4081
- writeCorsResponse(request, response, 400, "Invalid OAuth callback");
4082
- return;
4083
- }
4084
- resolveCode({ code });
4085
- response.once("finish", () => server.close());
4086
- writeHtmlResponse(
4087
- response,
4088
- 200,
4089
- "Dreamboard CLI login complete. You can return to your terminal."
4090
- );
4091
- return;
4092
- }
4093
- writeHtmlResponse(
4094
- response,
4095
- 200,
4096
- "Dreamboard CLI OAuth callback server"
4097
- );
4098
- } catch (error) {
4099
- rejectCode(
4100
- error instanceof Error ? error : new Error("Failed to handle OAuth callback.")
4101
- );
4102
- writeHtmlResponse(response, 500, "Dreamboard CLI login failed.");
4103
- }
4104
- }
4105
- );
4106
- try {
4107
- await new Promise((resolve, reject) => {
4108
- server.once("error", reject);
4109
- server.listen(portCandidate, "127.0.0.1", () => {
4110
- server.off("error", reject);
4111
- resolve();
4112
- });
4113
- });
4114
- } catch (error) {
4115
- const portError = error instanceof Error ? error : new Error("Failed to start OAuth callback server");
4116
- const configuredByEnv = Boolean(
4117
- process.env.DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT
4118
- );
4119
- const message = configuredByEnv ? `Failed to start OAuth callback server on configured port ${portCandidate}.` : `Failed to start OAuth callback server on port ${portCandidate}. Register this loopback redirect URI with Clerk and keep the port available, or set DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT.`;
4120
- const wrapped = new Error(`${message} ${portError.message}`);
4121
- server.close();
4122
- rejectCode(wrapped);
4123
- throw wrapped;
4124
- }
4125
- if (!server.listening) {
4126
- const error = new Error("Failed to start OAuth callback server.");
4127
- rejectCode(error);
4128
- throw error;
4129
- }
4130
- const timer = setTimeout(() => {
4131
- rejectCode(new Error("Login timed out."));
4132
- server?.close();
4133
- }, timeoutMs);
4134
- waitForCode.finally(() => clearTimeout(timer));
4135
- const port = portCandidateFromServer(server);
4136
- return {
4137
- port,
4138
- redirectUri: `http://127.0.0.1:${port}/oauth/callback`,
4139
- waitForCode,
4140
- close: () => server?.close()
4141
- };
4142
- }
4143
- function resolveOAuthCallbackPort() {
4144
- const rawPort = process.env.DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT?.trim();
4145
- if (!rawPort) {
4146
- return DEFAULT_OAUTH_CALLBACK_PORT;
4147
- }
4148
- const port = Number(rawPort);
4149
- if (!Number.isInteger(port) || port < 1 || port > 65535) {
4150
- throw new Error(
4151
- `Invalid DREAMBOARD_CLERK_OAUTH_REDIRECT_PORT '${rawPort}'. Expected a TCP port from 1 to 65535.`
4152
- );
4153
- }
4154
- return port;
4155
- }
4156
- function portCandidateFromServer(server) {
4157
- const address = server.address();
4158
- if (!address || typeof address === "string") {
4159
- throw new Error("Auth callback server did not expose a bound port.");
4160
- }
4161
- return address.port;
4162
- }
4163
- function writeCorsResponse(request, response, statusCode, body) {
4164
- const origin = request.headers.origin ?? "*";
4165
- response.writeHead(statusCode, {
4166
- "Access-Control-Allow-Origin": origin,
4167
- "Access-Control-Allow-Methods": "POST, OPTIONS",
4168
- "Access-Control-Allow-Headers": "Content-Type",
4169
- "Content-Type": "text/plain; charset=utf-8"
4170
- });
4171
- response.end(body);
4172
- }
4173
- function writeHtmlResponse(response, statusCode, body) {
4174
- response.writeHead(statusCode, {
4175
- "Content-Type": "text/html; charset=utf-8"
4176
- });
4177
- response.end(
4178
- `<!doctype html><meta charset="utf-8"><title>Dreamboard CLI</title><p>${escapeHtml(body)}</p>`
4179
- );
4180
- }
4181
- function escapeHtml(value) {
4182
- return value.replace(/[&<>"']/g, (char) => {
4183
- switch (char) {
4184
- case "&":
4185
- return "&amp;";
4186
- case "<":
4187
- return "&lt;";
4188
- case ">":
4189
- return "&gt;";
4190
- case '"':
4191
- return "&quot;";
4192
- default:
4193
- return "&#39;";
4194
- }
4195
- });
4196
- }
4197
- function openBrowser(url) {
4198
- const platform2 = process.platform;
4199
- let command;
4200
- if (platform2 === "darwin") {
4201
- command = ["open", url];
4202
- } else if (platform2 === "win32") {
4203
- command = ["cmd", "/c", "start", "", url];
4204
- } else {
4205
- command = ["xdg-open", url];
4206
- }
4207
- const [commandName, ...commandArgs] = command;
4208
- const child = spawn4(commandName, commandArgs, {
4209
- stdio: "ignore",
4210
- detached: true
4211
- });
4212
- child.unref();
4213
- }
4214
-
4215
4562
  // src/dev-host/start-dev-server.ts
4216
4563
  import { rmSync } from "fs";
4217
4564
  import { createRequire as createRequire3 } from "module";
@@ -7291,7 +7638,7 @@ async function assertKnownPlayerId(sessionId, playerId) {
7291
7638
  }
7292
7639
 
7293
7640
  // src/commands/login.ts
7294
- import crypto2 from "crypto";
7641
+ import crypto3 from "crypto";
7295
7642
  var login_default = defineCommand({
7296
7643
  meta: {
7297
7644
  name: "login",
@@ -7317,7 +7664,7 @@ var login_default = defineCommand({
7317
7664
  void 0,
7318
7665
  storedSession
7319
7666
  );
7320
- const state = crypto2.randomUUID();
7667
+ const state = crypto3.randomUUID();
7321
7668
  const pkce = createPkcePair();
7322
7669
  const server = await startOAuthCallbackServer(
7323
7670
  state,
@@ -8468,6 +8815,6 @@ function runDreamboardCli(internalSubCommands = {}) {
8468
8815
  void runMain(main).catch(handleFatalError);
8469
8816
  }
8470
8817
 
8471
- // src/index.published.ts
8472
- runDreamboardCli();
8818
+ // src/index.ts
8819
+ runDreamboardCli({ query: query_default, auth: auth_default });
8473
8820
  //# sourceMappingURL=index.js.map