tthr 0.0.20 → 0.0.21

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 (2) hide show
  1. package/dist/index.js +77 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1670,22 +1670,90 @@ function generateDbFile(tables) {
1670
1670
  lines.push("");
1671
1671
  return lines.join("\n");
1672
1672
  }
1673
- function generateApiFile(functionsDir, tables) {
1673
+ async function parseFunctionsDir(functionsDir) {
1674
+ const functions = [];
1675
+ if (!await fs6.pathExists(functionsDir)) {
1676
+ return functions;
1677
+ }
1678
+ const files = await fs6.readdir(functionsDir);
1679
+ for (const file of files) {
1680
+ if (!file.endsWith(".ts") && !file.endsWith(".js")) continue;
1681
+ const filePath = path6.join(functionsDir, file);
1682
+ const stat = await fs6.stat(filePath);
1683
+ if (!stat.isFile()) continue;
1684
+ const moduleName = file.replace(/\.(ts|js)$/, "");
1685
+ const source = await fs6.readFile(filePath, "utf-8");
1686
+ const exportRegex = /export\s+const\s+(\w+)\s*=\s*(query|mutation|action)\s*\(/g;
1687
+ let match;
1688
+ while ((match = exportRegex.exec(source)) !== null) {
1689
+ functions.push({
1690
+ name: match[1],
1691
+ moduleName
1692
+ });
1693
+ }
1694
+ }
1695
+ return functions;
1696
+ }
1697
+ async function generateApiFile(functionsDir) {
1698
+ const functions = await parseFunctionsDir(functionsDir);
1699
+ const moduleMap = /* @__PURE__ */ new Map();
1700
+ for (const fn of functions) {
1701
+ if (!moduleMap.has(fn.moduleName)) {
1702
+ moduleMap.set(fn.moduleName, []);
1703
+ }
1704
+ moduleMap.get(fn.moduleName).push(fn.name);
1705
+ }
1674
1706
  const lines = [
1675
1707
  "// Auto-generated by Tether CLI - do not edit manually",
1676
1708
  `// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
1677
1709
  "",
1678
1710
  "import { createApiProxy } from '@tthr/client';",
1679
- "import type { Schema } from './db';",
1680
- "",
1681
- "// API type placeholder - will be populated based on your functions",
1682
- "// eslint-disable-next-line @typescript-eslint/no-empty-object-type",
1683
- "export interface Api {}",
1684
1711
  "",
1685
- "// API client proxy - will be populated by the Tether runtime",
1686
- "export const api: Api = createApiProxy<Api>();",
1712
+ "/**",
1713
+ " * API function reference type for useQuery/useMutation.",
1714
+ ' * The _name property contains the function path (e.g., "users.list").',
1715
+ " */",
1716
+ "export interface ApiFunction<TArgs = unknown, TResult = unknown> {",
1717
+ " _name: string;",
1718
+ " _args?: TArgs;",
1719
+ " _result?: TResult;",
1720
+ "}",
1687
1721
  ""
1688
1722
  ];
1723
+ if (moduleMap.size > 0) {
1724
+ for (const [moduleName, fnNames] of moduleMap) {
1725
+ const interfaceName = moduleName.charAt(0).toUpperCase() + moduleName.slice(1) + "Api";
1726
+ lines.push(`export interface ${interfaceName} {`);
1727
+ for (const fnName of fnNames) {
1728
+ lines.push(` ${fnName}: ApiFunction;`);
1729
+ }
1730
+ lines.push("}");
1731
+ lines.push("");
1732
+ }
1733
+ lines.push("export interface Api {");
1734
+ for (const moduleName of moduleMap.keys()) {
1735
+ const interfaceName = moduleName.charAt(0).toUpperCase() + moduleName.slice(1) + "Api";
1736
+ lines.push(` ${moduleName}: ${interfaceName};`);
1737
+ }
1738
+ lines.push("}");
1739
+ } else {
1740
+ lines.push("/**");
1741
+ lines.push(" * Flexible API type that allows access to any function path.");
1742
+ lines.push(" * Functions are accessed as api.moduleName.functionName");
1743
+ lines.push(" * The actual types depend on your function definitions.");
1744
+ lines.push(" */");
1745
+ lines.push("export type Api = {");
1746
+ lines.push(" [module: string]: {");
1747
+ lines.push(" [fn: string]: ApiFunction;");
1748
+ lines.push(" };");
1749
+ lines.push("};");
1750
+ }
1751
+ lines.push("");
1752
+ lines.push("// API client proxy - provides typed access to your functions");
1753
+ lines.push("// On the client: returns { _name } references for useQuery/useMutation");
1754
+ lines.push("// In Tether functions: calls the actual function implementation");
1755
+ lines.push("export const api = createApiProxy<Api>();");
1756
+ lines.push("");
1689
1757
  return lines.join("\n");
1690
1758
  }
1691
1759
  async function generateCommand() {
@@ -1724,7 +1792,7 @@ async function generateCommand() {
1724
1792
  );
1725
1793
  await fs6.writeFile(
1726
1794
  path6.join(outputDir, "api.ts"),
1727
- generateApiFile(functionsDir, tables)
1795
+ await generateApiFile(functionsDir)
1728
1796
  );
1729
1797
  await fs6.writeFile(
1730
1798
  path6.join(outputDir, "index.ts"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tthr",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Tether CLI - project scaffolding, migrations, and deployment",
5
5
  "type": "module",
6
6
  "bin": {