tthr 0.0.32 → 0.0.33
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 +70 -212
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1840,218 +1840,77 @@ export * from './api';
|
|
|
1840
1840
|
}
|
|
1841
1841
|
}
|
|
1842
1842
|
|
|
1843
|
-
// src/commands/
|
|
1843
|
+
// src/commands/login.ts
|
|
1844
1844
|
import chalk6 from "chalk";
|
|
1845
1845
|
import ora5 from "ora";
|
|
1846
|
-
import fs7 from "fs-extra";
|
|
1847
|
-
import path7 from "path";
|
|
1848
|
-
import prompts2 from "prompts";
|
|
1849
|
-
async function migrateCommand(action, options) {
|
|
1850
|
-
await requireAuth();
|
|
1851
|
-
const configPath = path7.resolve(process.cwd(), "tether.config.ts");
|
|
1852
|
-
if (!await fs7.pathExists(configPath)) {
|
|
1853
|
-
console.log(chalk6.red("\nError: Not a Tether project"));
|
|
1854
|
-
console.log(chalk6.dim("Run `tthr init` to create a new project\n"));
|
|
1855
|
-
process.exit(1);
|
|
1856
|
-
}
|
|
1857
|
-
const migrationsDir = path7.resolve(process.cwd(), "tether", "migrations");
|
|
1858
|
-
switch (action) {
|
|
1859
|
-
case "create":
|
|
1860
|
-
await createMigration(migrationsDir, options.name);
|
|
1861
|
-
break;
|
|
1862
|
-
case "up":
|
|
1863
|
-
await runMigrations(migrationsDir, "up");
|
|
1864
|
-
break;
|
|
1865
|
-
case "down":
|
|
1866
|
-
await runMigrations(migrationsDir, "down");
|
|
1867
|
-
break;
|
|
1868
|
-
case "status":
|
|
1869
|
-
default:
|
|
1870
|
-
await showStatus(migrationsDir);
|
|
1871
|
-
break;
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
async function createMigration(migrationsDir, name) {
|
|
1875
|
-
console.log(chalk6.bold("\n\u26A1 Create migration\n"));
|
|
1876
|
-
let migrationName = name;
|
|
1877
|
-
if (!migrationName) {
|
|
1878
|
-
const response = await prompts2({
|
|
1879
|
-
type: "text",
|
|
1880
|
-
name: "name",
|
|
1881
|
-
message: "Migration name:",
|
|
1882
|
-
initial: "update_schema"
|
|
1883
|
-
});
|
|
1884
|
-
migrationName = response.name;
|
|
1885
|
-
if (!migrationName) {
|
|
1886
|
-
console.log(chalk6.red("Migration name is required"));
|
|
1887
|
-
process.exit(1);
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
const spinner = ora5("Creating migration...").start();
|
|
1891
|
-
try {
|
|
1892
|
-
await fs7.ensureDir(migrationsDir);
|
|
1893
|
-
const timestamp = Date.now();
|
|
1894
|
-
const filename = `${timestamp}_${migrationName}.sql`;
|
|
1895
|
-
const filepath = path7.join(migrationsDir, filename);
|
|
1896
|
-
await fs7.writeFile(
|
|
1897
|
-
filepath,
|
|
1898
|
-
`-- Migration: ${migrationName}
|
|
1899
|
-
-- Created at: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1900
|
-
|
|
1901
|
-
-- Up migration
|
|
1902
|
-
-- Add your schema changes here
|
|
1903
|
-
|
|
1904
|
-
-- Example:
|
|
1905
|
-
-- CREATE TABLE IF NOT EXISTS users (
|
|
1906
|
-
-- id TEXT PRIMARY KEY,
|
|
1907
|
-
-- email TEXT NOT NULL UNIQUE,
|
|
1908
|
-
-- name TEXT,
|
|
1909
|
-
-- created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1910
|
-
-- );
|
|
1911
|
-
|
|
1912
|
-
-- Down migration (for rollback)
|
|
1913
|
-
-- DROP TABLE IF EXISTS users;
|
|
1914
|
-
`
|
|
1915
|
-
);
|
|
1916
|
-
spinner.succeed("Migration created");
|
|
1917
|
-
console.log(chalk6.dim(`
|
|
1918
|
-
${filepath}
|
|
1919
|
-
`));
|
|
1920
|
-
} catch (error) {
|
|
1921
|
-
spinner.fail("Failed to create migration");
|
|
1922
|
-
console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
|
|
1923
|
-
process.exit(1);
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
async function runMigrations(migrationsDir, direction) {
|
|
1927
|
-
console.log(chalk6.bold(`
|
|
1928
|
-
\u26A1 Running migrations (${direction})
|
|
1929
|
-
`));
|
|
1930
|
-
const spinner = ora5("Checking migrations...").start();
|
|
1931
|
-
try {
|
|
1932
|
-
if (!await fs7.pathExists(migrationsDir)) {
|
|
1933
|
-
spinner.info("No migrations directory found");
|
|
1934
|
-
console.log(chalk6.dim("\nRun `tthr migrate create` to create your first migration\n"));
|
|
1935
|
-
return;
|
|
1936
|
-
}
|
|
1937
|
-
const files = await fs7.readdir(migrationsDir);
|
|
1938
|
-
const migrations = files.filter((f) => f.endsWith(".sql")).sort((a, b) => direction === "up" ? a.localeCompare(b) : b.localeCompare(a));
|
|
1939
|
-
if (migrations.length === 0) {
|
|
1940
|
-
spinner.info("No migrations found");
|
|
1941
|
-
console.log(chalk6.dim("\nRun `tthr migrate create` to create your first migration\n"));
|
|
1942
|
-
return;
|
|
1943
|
-
}
|
|
1944
|
-
spinner.text = `Found ${migrations.length} migration(s)`;
|
|
1945
|
-
spinner.succeed(`Would run ${migrations.length} migration(s)`);
|
|
1946
|
-
console.log("\nMigrations to run:");
|
|
1947
|
-
for (const migration of migrations) {
|
|
1948
|
-
console.log(chalk6.dim(` ${migration}`));
|
|
1949
|
-
}
|
|
1950
|
-
console.log(chalk6.yellow("\nNote: Migration execution not yet implemented\n"));
|
|
1951
|
-
} catch (error) {
|
|
1952
|
-
spinner.fail("Failed to run migrations");
|
|
1953
|
-
console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
|
|
1954
|
-
process.exit(1);
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
async function showStatus(migrationsDir) {
|
|
1958
|
-
console.log(chalk6.bold("\n\u26A1 Migration status\n"));
|
|
1959
|
-
try {
|
|
1960
|
-
if (!await fs7.pathExists(migrationsDir)) {
|
|
1961
|
-
console.log(chalk6.dim("No migrations directory found"));
|
|
1962
|
-
console.log(chalk6.dim("\nRun `tthr migrate create` to create your first migration\n"));
|
|
1963
|
-
return;
|
|
1964
|
-
}
|
|
1965
|
-
const files = await fs7.readdir(migrationsDir);
|
|
1966
|
-
const migrations = files.filter((f) => f.endsWith(".sql")).sort();
|
|
1967
|
-
if (migrations.length === 0) {
|
|
1968
|
-
console.log(chalk6.dim("No migrations found"));
|
|
1969
|
-
console.log(chalk6.dim("\nRun `tthr migrate create` to create your first migration\n"));
|
|
1970
|
-
return;
|
|
1971
|
-
}
|
|
1972
|
-
console.log(`Found ${migrations.length} migration(s):
|
|
1973
|
-
`);
|
|
1974
|
-
for (const migration of migrations) {
|
|
1975
|
-
console.log(chalk6.yellow(" \u25CB") + ` ${migration} ${chalk6.dim("(pending)")}`);
|
|
1976
|
-
}
|
|
1977
|
-
console.log();
|
|
1978
|
-
} catch (error) {
|
|
1979
|
-
console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
|
|
1980
|
-
process.exit(1);
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
// src/commands/login.ts
|
|
1985
|
-
import chalk7 from "chalk";
|
|
1986
|
-
import ora6 from "ora";
|
|
1987
1846
|
import os from "os";
|
|
1988
1847
|
var isDev3 = process.env.NODE_ENV === "development" || process.env.TETHER_DEV === "true";
|
|
1989
1848
|
var API_URL3 = isDev3 ? "http://localhost:3001/api/v1" : "https://tether-api.strands.gg/api/v1";
|
|
1990
1849
|
var AUTH_URL = isDev3 ? "http://localhost:3000/cli" : "https://tthr.io/cli";
|
|
1991
1850
|
async function loginCommand() {
|
|
1992
|
-
console.log(
|
|
1851
|
+
console.log(chalk6.bold("\u26A1 Login to Tether\n"));
|
|
1993
1852
|
const existing = await getCredentials();
|
|
1994
1853
|
if (existing) {
|
|
1995
|
-
console.log(
|
|
1996
|
-
console.log(
|
|
1854
|
+
console.log(chalk6.green("\u2713") + ` Already logged in as ${chalk6.cyan(existing.email)}`);
|
|
1855
|
+
console.log(chalk6.dim("\nRun `tthr logout` to sign out\n"));
|
|
1997
1856
|
return;
|
|
1998
1857
|
}
|
|
1999
|
-
const spinner =
|
|
1858
|
+
const spinner = ora5("Generating authentication code...").start();
|
|
2000
1859
|
try {
|
|
2001
1860
|
const deviceCode = await requestDeviceCode();
|
|
2002
1861
|
spinner.stop();
|
|
2003
1862
|
const authUrl = `${AUTH_URL}/${deviceCode.userCode}`;
|
|
2004
|
-
console.log(
|
|
2005
|
-
console.log(
|
|
1863
|
+
console.log(chalk6.dim("Open this URL in your browser to authenticate:\n"));
|
|
1864
|
+
console.log(chalk6.cyan.bold(` ${authUrl}
|
|
2006
1865
|
`));
|
|
2007
|
-
console.log(
|
|
1866
|
+
console.log(chalk6.dim(`Your code: ${chalk6.white.bold(deviceCode.userCode)}
|
|
2008
1867
|
`));
|
|
2009
1868
|
const credentials = await pollForApproval(deviceCode.deviceCode, deviceCode.interval, deviceCode.expiresIn);
|
|
2010
1869
|
await saveCredentials(credentials);
|
|
2011
|
-
console.log(
|
|
1870
|
+
console.log(chalk6.green("\u2713") + ` Logged in as ${chalk6.cyan(credentials.email)}`);
|
|
2012
1871
|
console.log();
|
|
2013
1872
|
} catch (error) {
|
|
2014
1873
|
spinner.fail("Authentication failed");
|
|
2015
|
-
console.error(
|
|
2016
|
-
console.log(
|
|
1874
|
+
console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
|
|
1875
|
+
console.log(chalk6.dim("\nTry again or visit https://tthr.io/docs/cli for help\n"));
|
|
2017
1876
|
process.exit(1);
|
|
2018
1877
|
}
|
|
2019
1878
|
}
|
|
2020
1879
|
async function logoutCommand() {
|
|
2021
|
-
console.log(
|
|
1880
|
+
console.log(chalk6.bold("\n\u26A1 Logout from Tether\n"));
|
|
2022
1881
|
const credentials = await getCredentials();
|
|
2023
1882
|
if (!credentials) {
|
|
2024
|
-
console.log(
|
|
1883
|
+
console.log(chalk6.dim("Not logged in\n"));
|
|
2025
1884
|
return;
|
|
2026
1885
|
}
|
|
2027
|
-
const spinner =
|
|
1886
|
+
const spinner = ora5("Logging out...").start();
|
|
2028
1887
|
try {
|
|
2029
1888
|
await clearCredentials();
|
|
2030
|
-
spinner.succeed(`Logged out from ${
|
|
1889
|
+
spinner.succeed(`Logged out from ${chalk6.cyan(credentials.email)}`);
|
|
2031
1890
|
console.log();
|
|
2032
1891
|
} catch (error) {
|
|
2033
1892
|
spinner.fail("Logout failed");
|
|
2034
|
-
console.error(
|
|
1893
|
+
console.error(chalk6.red(error instanceof Error ? error.message : "Unknown error"));
|
|
2035
1894
|
process.exit(1);
|
|
2036
1895
|
}
|
|
2037
1896
|
}
|
|
2038
1897
|
async function whoamiCommand() {
|
|
2039
1898
|
const credentials = await getCredentials();
|
|
2040
1899
|
if (!credentials) {
|
|
2041
|
-
console.log(
|
|
2042
|
-
console.log(
|
|
1900
|
+
console.log(chalk6.dim("\nNot logged in"));
|
|
1901
|
+
console.log(chalk6.dim("Run `tthr login` to authenticate\n"));
|
|
2043
1902
|
return;
|
|
2044
1903
|
}
|
|
2045
|
-
console.log(
|
|
2046
|
-
console.log(` Email: ${
|
|
2047
|
-
console.log(` User ID: ${
|
|
1904
|
+
console.log(chalk6.bold("\n\u26A1 Current user\n"));
|
|
1905
|
+
console.log(` Email: ${chalk6.cyan(credentials.email)}`);
|
|
1906
|
+
console.log(` User ID: ${chalk6.dim(credentials.userId)}`);
|
|
2048
1907
|
if (credentials.expiresAt) {
|
|
2049
1908
|
const expiresAt = new Date(credentials.expiresAt);
|
|
2050
1909
|
const now = /* @__PURE__ */ new Date();
|
|
2051
1910
|
if (expiresAt > now) {
|
|
2052
|
-
console.log(` Session: ${
|
|
1911
|
+
console.log(` Session: ${chalk6.green("Active")}`);
|
|
2053
1912
|
} else {
|
|
2054
|
-
console.log(` Session: ${
|
|
1913
|
+
console.log(` Session: ${chalk6.yellow("Expired")}`);
|
|
2055
1914
|
}
|
|
2056
1915
|
}
|
|
2057
1916
|
console.log();
|
|
@@ -2093,20 +1952,20 @@ async function requestDeviceCode() {
|
|
|
2093
1952
|
async function pollForApproval(deviceCode, interval, expiresIn) {
|
|
2094
1953
|
const startTime = Date.now();
|
|
2095
1954
|
const expiresAt = startTime + expiresIn * 1e3;
|
|
2096
|
-
const spinner =
|
|
1955
|
+
const spinner = ora5("").start();
|
|
2097
1956
|
const updateCountdown = () => {
|
|
2098
1957
|
const remaining = Math.max(0, Math.ceil((expiresAt - Date.now()) / 1e3));
|
|
2099
1958
|
const mins = Math.floor(remaining / 60);
|
|
2100
1959
|
const secs = remaining % 60;
|
|
2101
1960
|
const timeStr = mins > 0 ? `${mins}:${secs.toString().padStart(2, "0")}` : `${secs}s`;
|
|
2102
|
-
spinner.text = `Waiting for approval... ${
|
|
1961
|
+
spinner.text = `Waiting for approval... ${chalk6.dim(`(${timeStr} remaining)`)}`;
|
|
2103
1962
|
};
|
|
2104
1963
|
updateCountdown();
|
|
2105
1964
|
const countdownInterval = setInterval(updateCountdown, 1e3);
|
|
2106
1965
|
try {
|
|
2107
1966
|
while (Date.now() < expiresAt) {
|
|
2108
1967
|
await sleep(interval * 1e3);
|
|
2109
|
-
spinner.text = `Checking... ${
|
|
1968
|
+
spinner.text = `Checking... ${chalk6.dim(`(${Math.ceil((expiresAt - Date.now()) / 1e3)}s remaining)`)}`;
|
|
2110
1969
|
const response = await fetch(`${API_URL3}/auth/device/${deviceCode}`, {
|
|
2111
1970
|
method: "GET"
|
|
2112
1971
|
}).catch(() => null);
|
|
@@ -2139,10 +1998,10 @@ function sleep(ms) {
|
|
|
2139
1998
|
}
|
|
2140
1999
|
|
|
2141
2000
|
// src/commands/update.ts
|
|
2142
|
-
import
|
|
2143
|
-
import
|
|
2144
|
-
import
|
|
2145
|
-
import
|
|
2001
|
+
import chalk7 from "chalk";
|
|
2002
|
+
import ora6 from "ora";
|
|
2003
|
+
import fs7 from "fs-extra";
|
|
2004
|
+
import path7 from "path";
|
|
2146
2005
|
import { execSync as execSync2 } from "child_process";
|
|
2147
2006
|
var TETHER_PACKAGES = [
|
|
2148
2007
|
"@tthr/client",
|
|
@@ -2154,13 +2013,13 @@ var TETHER_PACKAGES = [
|
|
|
2154
2013
|
];
|
|
2155
2014
|
function detectPackageManager() {
|
|
2156
2015
|
const cwd = process.cwd();
|
|
2157
|
-
if (
|
|
2016
|
+
if (fs7.existsSync(path7.join(cwd, "bun.lockb")) || fs7.existsSync(path7.join(cwd, "bun.lock"))) {
|
|
2158
2017
|
return "bun";
|
|
2159
2018
|
}
|
|
2160
|
-
if (
|
|
2019
|
+
if (fs7.existsSync(path7.join(cwd, "pnpm-lock.yaml"))) {
|
|
2161
2020
|
return "pnpm";
|
|
2162
2021
|
}
|
|
2163
|
-
if (
|
|
2022
|
+
if (fs7.existsSync(path7.join(cwd, "yarn.lock"))) {
|
|
2164
2023
|
return "yarn";
|
|
2165
2024
|
}
|
|
2166
2025
|
return "npm";
|
|
@@ -2190,14 +2049,14 @@ async function getLatestVersion2(packageName) {
|
|
|
2190
2049
|
}
|
|
2191
2050
|
}
|
|
2192
2051
|
async function updateCommand(options) {
|
|
2193
|
-
const packageJsonPath =
|
|
2194
|
-
if (!await
|
|
2195
|
-
console.log(
|
|
2196
|
-
console.log(
|
|
2052
|
+
const packageJsonPath = path7.resolve(process.cwd(), "package.json");
|
|
2053
|
+
if (!await fs7.pathExists(packageJsonPath)) {
|
|
2054
|
+
console.log(chalk7.red("\nError: No package.json found"));
|
|
2055
|
+
console.log(chalk7.dim("Make sure you're in the root of your project\n"));
|
|
2197
2056
|
process.exit(1);
|
|
2198
2057
|
}
|
|
2199
|
-
console.log(
|
|
2200
|
-
const packageJson = await
|
|
2058
|
+
console.log(chalk7.bold("\n\u26A1 Updating Tether packages\n"));
|
|
2059
|
+
const packageJson = await fs7.readJson(packageJsonPath);
|
|
2201
2060
|
const deps = packageJson.dependencies || {};
|
|
2202
2061
|
const devDeps = packageJson.devDependencies || {};
|
|
2203
2062
|
const installedDeps = [];
|
|
@@ -2210,13 +2069,13 @@ async function updateCommand(options) {
|
|
|
2210
2069
|
}
|
|
2211
2070
|
}
|
|
2212
2071
|
if (installedDeps.length === 0) {
|
|
2213
|
-
console.log(
|
|
2214
|
-
console.log(
|
|
2072
|
+
console.log(chalk7.yellow(" No updatable Tether packages found in package.json"));
|
|
2073
|
+
console.log(chalk7.dim(" Tether packages start with @tthr/ (workspace: dependencies are skipped)\n"));
|
|
2215
2074
|
return;
|
|
2216
2075
|
}
|
|
2217
|
-
console.log(
|
|
2076
|
+
console.log(chalk7.dim(` Found ${installedDeps.length} Tether package(s):
|
|
2218
2077
|
`));
|
|
2219
|
-
const spinner =
|
|
2078
|
+
const spinner = ora6("Checking for updates...").start();
|
|
2220
2079
|
const packagesToUpdate = [];
|
|
2221
2080
|
for (const pkg of installedDeps) {
|
|
2222
2081
|
const latestVersion = await getLatestVersion2(pkg.name);
|
|
@@ -2230,32 +2089,32 @@ async function updateCommand(options) {
|
|
|
2230
2089
|
isDev: pkg.isDev
|
|
2231
2090
|
});
|
|
2232
2091
|
} else {
|
|
2233
|
-
console.log(
|
|
2092
|
+
console.log(chalk7.dim(` ${pkg.name}@${currentClean} (up to date)`));
|
|
2234
2093
|
}
|
|
2235
2094
|
}
|
|
2236
2095
|
}
|
|
2237
2096
|
spinner.stop();
|
|
2238
2097
|
if (packagesToUpdate.length === 0) {
|
|
2239
|
-
console.log(
|
|
2098
|
+
console.log(chalk7.green("\n\u2713 All Tether packages are up to date\n"));
|
|
2240
2099
|
return;
|
|
2241
2100
|
}
|
|
2242
|
-
console.log(
|
|
2101
|
+
console.log(chalk7.cyan("\n Updates available:\n"));
|
|
2243
2102
|
for (const pkg of packagesToUpdate) {
|
|
2244
2103
|
console.log(
|
|
2245
|
-
|
|
2104
|
+
chalk7.white(` ${pkg.name}`) + chalk7.red(` ${pkg.current}`) + chalk7.dim(" \u2192 ") + chalk7.green(`${pkg.latest}`) + (pkg.isDev ? chalk7.dim(" (dev)") : "")
|
|
2246
2105
|
);
|
|
2247
2106
|
}
|
|
2248
2107
|
if (options.dryRun) {
|
|
2249
|
-
console.log(
|
|
2108
|
+
console.log(chalk7.yellow("\n Dry run - no packages were updated\n"));
|
|
2250
2109
|
return;
|
|
2251
2110
|
}
|
|
2252
2111
|
const pm = detectPackageManager();
|
|
2253
|
-
console.log(
|
|
2112
|
+
console.log(chalk7.dim(`
|
|
2254
2113
|
Using ${pm} to update packages...
|
|
2255
2114
|
`));
|
|
2256
2115
|
const depsToUpdate = packagesToUpdate.filter((p) => !p.isDev).map((p) => `${p.name}@latest`);
|
|
2257
2116
|
const devDepsToUpdate = packagesToUpdate.filter((p) => p.isDev).map((p) => `${p.name}@latest`);
|
|
2258
|
-
const updateSpinner =
|
|
2117
|
+
const updateSpinner = ora6("Installing updates...").start();
|
|
2259
2118
|
try {
|
|
2260
2119
|
if (depsToUpdate.length > 0) {
|
|
2261
2120
|
const cmd = getInstallCommand2(pm, depsToUpdate, false);
|
|
@@ -2266,43 +2125,43 @@ async function updateCommand(options) {
|
|
|
2266
2125
|
execSync2(cmd, { stdio: "pipe", cwd: process.cwd() });
|
|
2267
2126
|
}
|
|
2268
2127
|
updateSpinner.succeed("Packages updated successfully");
|
|
2269
|
-
console.log(
|
|
2128
|
+
console.log(chalk7.green(`
|
|
2270
2129
|
\u2713 Updated ${packagesToUpdate.length} package(s)
|
|
2271
2130
|
`));
|
|
2272
2131
|
} catch (error) {
|
|
2273
2132
|
updateSpinner.fail("Failed to update packages");
|
|
2274
|
-
console.error(
|
|
2133
|
+
console.error(chalk7.red(error instanceof Error ? error.message : "Unknown error"));
|
|
2275
2134
|
process.exit(1);
|
|
2276
2135
|
}
|
|
2277
2136
|
}
|
|
2278
2137
|
|
|
2279
2138
|
// src/commands/exec.ts
|
|
2280
|
-
import
|
|
2281
|
-
import
|
|
2282
|
-
import
|
|
2283
|
-
import
|
|
2139
|
+
import chalk8 from "chalk";
|
|
2140
|
+
import ora7 from "ora";
|
|
2141
|
+
import fs8 from "fs-extra";
|
|
2142
|
+
import path8 from "path";
|
|
2284
2143
|
var isDev4 = process.env.NODE_ENV === "development" || process.env.TETHER_DEV === "true";
|
|
2285
2144
|
var API_URL4 = isDev4 ? "http://localhost:3001/api/v1" : "https://tether-api.strands.gg/api/v1";
|
|
2286
2145
|
async function execCommand(sql) {
|
|
2287
2146
|
if (!sql || sql.trim() === "") {
|
|
2288
|
-
console.log(
|
|
2289
|
-
console.log(
|
|
2147
|
+
console.log(chalk8.red("\nError: SQL query required"));
|
|
2148
|
+
console.log(chalk8.dim('Usage: tthr exec "SELECT * FROM table_name"\n'));
|
|
2290
2149
|
process.exit(1);
|
|
2291
2150
|
}
|
|
2292
2151
|
const credentials = await requireAuth();
|
|
2293
|
-
const envPath =
|
|
2152
|
+
const envPath = path8.resolve(process.cwd(), ".env");
|
|
2294
2153
|
let projectId;
|
|
2295
|
-
if (await
|
|
2296
|
-
const envContent = await
|
|
2154
|
+
if (await fs8.pathExists(envPath)) {
|
|
2155
|
+
const envContent = await fs8.readFile(envPath, "utf-8");
|
|
2297
2156
|
const match = envContent.match(/TETHER_PROJECT_ID=(.+)/);
|
|
2298
2157
|
projectId = match?.[1]?.trim();
|
|
2299
2158
|
}
|
|
2300
2159
|
if (!projectId) {
|
|
2301
|
-
console.log(
|
|
2302
|
-
console.log(
|
|
2160
|
+
console.log(chalk8.red("\nError: Project ID not found"));
|
|
2161
|
+
console.log(chalk8.dim("Make sure TETHER_PROJECT_ID is set in your .env file\n"));
|
|
2303
2162
|
process.exit(1);
|
|
2304
2163
|
}
|
|
2305
|
-
const spinner =
|
|
2164
|
+
const spinner = ora7("Executing query...").start();
|
|
2306
2165
|
try {
|
|
2307
2166
|
const response = await fetch(`${API_URL4}/projects/${projectId}/exec`, {
|
|
2308
2167
|
method: "POST",
|
|
@@ -2322,24 +2181,24 @@ async function execCommand(sql) {
|
|
|
2322
2181
|
if (result.columns && result.rows) {
|
|
2323
2182
|
console.log();
|
|
2324
2183
|
if (result.rows.length === 0) {
|
|
2325
|
-
console.log(
|
|
2184
|
+
console.log(chalk8.dim(" No rows returned"));
|
|
2326
2185
|
} else {
|
|
2327
|
-
console.log(
|
|
2328
|
-
console.log(
|
|
2186
|
+
console.log(chalk8.bold(" " + result.columns.join(" ")));
|
|
2187
|
+
console.log(chalk8.dim(" " + result.columns.map(() => "--------").join(" ")));
|
|
2329
2188
|
for (const row of result.rows) {
|
|
2330
2189
|
const values = result.columns.map((col) => {
|
|
2331
2190
|
const val = row[col];
|
|
2332
|
-
if (val === null) return
|
|
2191
|
+
if (val === null) return chalk8.dim("NULL");
|
|
2333
2192
|
if (typeof val === "object") return JSON.stringify(val);
|
|
2334
2193
|
return String(val);
|
|
2335
2194
|
});
|
|
2336
2195
|
console.log(" " + values.join(" "));
|
|
2337
2196
|
}
|
|
2338
|
-
console.log(
|
|
2197
|
+
console.log(chalk8.dim(`
|
|
2339
2198
|
${result.rows.length} row(s)`));
|
|
2340
2199
|
}
|
|
2341
2200
|
} else if (result.rowsAffected !== void 0) {
|
|
2342
|
-
console.log(
|
|
2201
|
+
console.log(chalk8.dim(`
|
|
2343
2202
|
${result.rowsAffected} row(s) affected`));
|
|
2344
2203
|
}
|
|
2345
2204
|
console.log();
|
|
@@ -2355,7 +2214,6 @@ program.name("tthr").description("Tether CLI - Realtime SQLite for modern applic
|
|
|
2355
2214
|
program.command("init [name]").description("Create a new Tether project").option("-t, --template <template>", "Project template (vue, svelte, react, vanilla)", "vue").action(initCommand);
|
|
2356
2215
|
program.command("dev").description("Start local development server with hot reload").option("-p, --port <port>", "Port to run on", "3001").action(devCommand);
|
|
2357
2216
|
program.command("generate").alias("gen").description("Generate types from schema").action(generateCommand);
|
|
2358
|
-
program.command("migrate").description("Database migrations").argument("[action]", "Migration action: create, up, down, status", "status").option("-n, --name <name>", "Migration name (for create)").action(migrateCommand);
|
|
2359
2217
|
program.command("deploy").description("Deploy schema and functions to Tether").option("-s, --schema", "Deploy schema only").option("-f, --functions", "Deploy functions only").option("--dry-run", "Show what would be deployed without deploying").action(deployCommand);
|
|
2360
2218
|
program.command("login").description("Authenticate with Tether").action(loginCommand);
|
|
2361
2219
|
program.command("logout").description("Sign out of Tether").action(logoutCommand);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tthr",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Tether CLI - project scaffolding
|
|
3
|
+
"version": "0.0.33",
|
|
4
|
+
"description": "Tether CLI - project scaffolding and deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"tthr": "./dist/index.js"
|