better-convex 0.6.4 → 0.7.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.
Files changed (47) hide show
  1. package/dist/aggregate/index.d.ts +388 -0
  2. package/dist/aggregate/index.js +37 -0
  3. package/dist/{auth-client → auth/client}/index.js +1 -1
  4. package/dist/auth/http/index.d.ts +63 -0
  5. package/dist/auth/http/index.js +429 -0
  6. package/dist/auth/index.d.ts +18991 -175
  7. package/dist/auth/index.js +373 -686
  8. package/dist/{auth-nextjs → auth/nextjs}/index.d.ts +3 -5
  9. package/dist/{auth-nextjs → auth/nextjs}/index.js +3 -5
  10. package/dist/{caller-factory-B1FvYSKr.js → caller-factory-Dmgv8MLS.js} +15 -12
  11. package/dist/cli.mjs +2601 -13
  12. package/dist/codegen-Cz1idI3-.mjs +969 -0
  13. package/dist/{create-schema-orm-DplxTtYj.js → create-schema-orm-69VF4CFV.js} +4 -3
  14. package/dist/crpc/index.d.ts +2 -2
  15. package/dist/crpc/index.js +3 -3
  16. package/dist/{http-types-BRLY10NX.d.ts → http-types-BCf2wCgp.d.ts} +25 -25
  17. package/dist/meta-utils-DDVYp9Xf.js +117 -0
  18. package/dist/orm/index.d.ts +4 -3012
  19. package/dist/orm/index.js +9631 -2
  20. package/dist/{index-BQkhP2ny.d.ts → procedure-caller-CcjtUFvL.d.ts} +211 -74
  21. package/dist/query-context-BDSis9rT.js +1518 -0
  22. package/dist/query-context-DGExXZIV.d.ts +42 -0
  23. package/dist/react/index.d.ts +31 -35
  24. package/dist/react/index.js +145 -58
  25. package/dist/rsc/index.d.ts +4 -7
  26. package/dist/rsc/index.js +14 -10
  27. package/dist/runtime-B9xQFY8W.js +2280 -0
  28. package/dist/server/index.d.ts +3 -4
  29. package/dist/server/index.js +384 -10
  30. package/dist/{types-o-5rYcTr.d.ts → types-CIBGEYXq.d.ts} +4 -3
  31. package/dist/types-DgwvxKbT.d.ts +4 -0
  32. package/dist/watcher.mjs +8 -8
  33. package/dist/where-clause-compiler-CRP-i1Qa.d.ts +3463 -0
  34. package/package.json +14 -10
  35. package/dist/codegen-DkpPBVPn.mjs +0 -189
  36. package/dist/context-utils-DSuX99Da.d.ts +0 -17
  37. package/dist/meta-utils-DCpLSBWB.js +0 -41
  38. package/dist/orm-BKc-pwj_.js +0 -8821
  39. /package/dist/{auth-client → auth/client}/index.d.ts +0 -0
  40. /package/dist/{auth-config → auth/config}/index.d.ts +0 -0
  41. /package/dist/{auth-config → auth/config}/index.js +0 -0
  42. /package/dist/{create-schema-DhWXOhnU.js → create-schema-BdZOL6ns.js} +0 -0
  43. /package/dist/{customFunctions-C1okqCzL.js → customFunctions-CZnCwoR3.js} +0 -0
  44. /package/dist/{error-BZUhlhYz.js → error-Be4OcwwD.js} +0 -0
  45. /package/dist/{query-options-BL1Q0X7q.js → query-options-B0c1b6pZ.js} +0 -0
  46. /package/dist/{transformer-CTNSPjwp.js → transformer-Dh0w2py0.js} +0 -0
  47. /package/dist/{types-jftzhhuc.d.ts → types-DwGkkq2s.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-convex",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "Better Convex - React Query integration and CLI tools for Convex",
5
5
  "keywords": [
6
6
  "convex",
@@ -12,10 +12,12 @@
12
12
  "sideEffects": false,
13
13
  "type": "module",
14
14
  "exports": {
15
+ "./aggregate": "./dist/aggregate/index.js",
15
16
  "./auth": "./dist/auth/index.js",
16
- "./auth-client": "./dist/auth-client/index.js",
17
- "./auth-config": "./dist/auth-config/index.js",
18
- "./auth-nextjs": "./dist/auth-nextjs/index.js",
17
+ "./auth/client": "./dist/auth/client/index.js",
18
+ "./auth/config": "./dist/auth/config/index.js",
19
+ "./auth/http": "./dist/auth/http/index.js",
20
+ "./auth/nextjs": "./dist/auth/nextjs/index.js",
19
21
  "./crpc": "./dist/crpc/index.js",
20
22
  "./orm": "./dist/orm/index.js",
21
23
  "./react": "./dist/react/index.js",
@@ -37,27 +39,29 @@
37
39
  "typecheck:types": "tsc --project ../../convex/test-types/tsconfig.json"
38
40
  },
39
41
  "dependencies": {
42
+ "@clack/prompts": "^0.11.0",
40
43
  "@convex-dev/better-auth": "^0.10.10",
41
44
  "chokidar": "^5.0.0",
42
45
  "common-tags": "^1.8.2",
43
- "dotenv": "^17.2.3",
46
+ "dotenv": "^17.3.1",
47
+ "esbuild": "^0.27.3",
44
48
  "execa": "^9.6.1",
45
49
  "jiti": "^2.6.1",
46
- "jotai": "^2.17.0",
50
+ "jotai": "^2.18.0",
47
51
  "jotai-x": "^2.3.3",
48
52
  "picocolors": "^1.1.1",
49
- "remeda": "^2.33.4",
50
- "type-fest": "^5.4.2"
53
+ "remeda": "^2.33.6",
54
+ "type-fest": "^5.4.4"
51
55
  },
52
56
  "devDependencies": {
53
57
  "@rollup/plugin-babel": "^6.1.0",
54
58
  "babel-plugin-react-compiler": "^1.0.0",
55
- "tsdown": "^0.20.1"
59
+ "tsdown": "^0.20.3"
56
60
  },
57
61
  "peerDependencies": {
58
62
  "@tanstack/react-query": ">=5",
59
63
  "better-auth": ">=1.4.9",
60
- "convex": ">=1.31",
64
+ "convex": ">=1.32",
61
65
  "hono": ">=4",
62
66
  "next": ">=14",
63
67
  "react": ">=18",
@@ -1,189 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import { createJiti } from "jiti";
5
-
6
- //#region src/shared/meta-utils.ts
7
- /** Files to exclude from meta generation */
8
- const EXCLUDED_FILES = new Set([
9
- "schema.ts",
10
- "convex.config.ts",
11
- "auth.config.ts"
12
- ]);
13
- /**
14
- * Check if a file path should be included in meta generation.
15
- * Filters out private files/directories (prefixed with _) and config files.
16
- */
17
- function isValidConvexFile(file) {
18
- if (file.startsWith("_") || file.includes("/_")) return false;
19
- const basename = file.split("/").pop() ?? "";
20
- if (EXCLUDED_FILES.has(basename)) return false;
21
- return true;
22
- }
23
-
24
- //#endregion
25
- //#region src/cli/codegen.ts
26
- /** Valid JS identifier pattern for object keys */
27
- const VALID_IDENTIFIER_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
28
- /** Pattern to strip .ts extension */
29
- const TS_EXTENSION_RE = /\.ts$/;
30
- function listFilesRecursive(cwd, relDir = "") {
31
- const absDir = path.join(cwd, relDir);
32
- const entries = fs.readdirSync(absDir, { withFileTypes: true });
33
- const files = [];
34
- for (const entry of entries) {
35
- const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
36
- if (entry.isDirectory()) {
37
- files.push(...listFilesRecursive(cwd, relPath));
38
- continue;
39
- }
40
- if (entry.isFile()) files.push(relPath);
41
- }
42
- return files;
43
- }
44
- function getConvexConfig(outputDir) {
45
- const convexConfigPath = path.join(process.cwd(), "convex.json");
46
- const functionsDir = (fs.existsSync(convexConfigPath) ? JSON.parse(fs.readFileSync(convexConfigPath, "utf-8")) : {}).functions || "convex";
47
- return {
48
- functionsDir: path.join(process.cwd(), functionsDir),
49
- outputFile: path.join(process.cwd(), outputDir || "convex/shared", "meta.ts")
50
- };
51
- }
52
- /**
53
- * Check if a value is a CRPCHttpRouter (has _def.router === true)
54
- */
55
- function isCRPCHttpRouter(value) {
56
- return typeof value === "object" && value !== null && "_def" in value && value._def?.router === true;
57
- }
58
- /**
59
- * Import a module using jiti and extract CRPC metadata from exports
60
- */
61
- async function parseModuleRuntime(filePath, jitiInstance) {
62
- const result = {};
63
- const httpRoutes = {};
64
- const isHttp = filePath.endsWith("http.ts");
65
- const module = await jitiInstance.import(filePath);
66
- if (!module || typeof module !== "object") {
67
- if (isHttp) console.error(" http.ts: module is empty or not an object");
68
- return {
69
- meta: null,
70
- httpRoutes: {}
71
- };
72
- }
73
- for (const [name, value] of Object.entries(module)) {
74
- if (name.startsWith("_")) continue;
75
- const meta = value?._crpcMeta;
76
- if (meta?.type) {
77
- if (meta.internal) continue;
78
- const fnMeta = { type: meta.type };
79
- if (meta.auth) fnMeta.auth = meta.auth;
80
- for (const [key, val] of Object.entries(meta)) if (key !== "type" && key !== "internal" && val !== void 0) fnMeta[key] = val;
81
- result[name] = fnMeta;
82
- }
83
- const httpRoute = value?._crpcHttpRoute;
84
- if (httpRoute?.path && httpRoute?.method) httpRoutes[name] = {
85
- path: httpRoute.path,
86
- method: httpRoute.method
87
- };
88
- if (isCRPCHttpRouter(value)) for (const [procPath, procedure] of Object.entries(value._def.procedures)) {
89
- const route = procedure._crpcHttpRoute;
90
- if (route?.path && route?.method) httpRoutes[procPath] = {
91
- path: route.path,
92
- method: route.method
93
- };
94
- }
95
- }
96
- return {
97
- meta: Object.keys(result).length > 0 ? result : null,
98
- httpRoutes
99
- };
100
- }
101
- async function generateMeta(outputDir, options) {
102
- const startTime = Date.now();
103
- const { functionsDir, outputFile } = getConvexConfig(outputDir);
104
- const debug = options?.debug ?? false;
105
- const silent = options?.silent ?? false;
106
- if (debug) console.info("🔍 Scanning Convex functions for metadata...\n");
107
- const jitiInstance = createJiti(process.cwd(), {
108
- interopDefault: true,
109
- moduleCache: false
110
- });
111
- const meta = {};
112
- const allHttpRoutes = {};
113
- let totalFunctions = 0;
114
- const files = listFilesRecursive(functionsDir).filter((file) => file.endsWith(".ts") && isValidConvexFile(file));
115
- for (const file of files) {
116
- const filePath = path.join(functionsDir, file);
117
- const moduleName = file.replace(TS_EXTENSION_RE, "");
118
- try {
119
- const { meta: moduleMeta, httpRoutes } = await parseModuleRuntime(filePath, jitiInstance);
120
- if (moduleMeta) {
121
- meta[moduleName] = moduleMeta;
122
- const fnCount = Object.keys(moduleMeta).length;
123
- totalFunctions += fnCount;
124
- if (debug) console.info(` ✓ ${moduleName}: ${fnCount} functions`);
125
- }
126
- if (Object.keys(httpRoutes).length > 0 && debug) console.info(` ✓ ${moduleName}: ${Object.keys(httpRoutes).length} HTTP routes`);
127
- Object.assign(allHttpRoutes, httpRoutes);
128
- } catch (error) {
129
- if (debug || file === "http.ts") console.error(` ⚠ Failed to parse ${file}:`, error);
130
- }
131
- }
132
- const formatKey = (key) => VALID_IDENTIFIER_RE.test(key) ? key : `'${key}'`;
133
- const metaEntries = Object.entries(meta).map(([module, fns]) => {
134
- const fnEntries = Object.entries(fns).map(([fn, fnMeta]) => {
135
- const metaProps = [];
136
- for (const [key, value] of Object.entries(fnMeta).sort()) {
137
- if (value === void 0) continue;
138
- if (typeof value === "string") metaProps.push(`${key}: '${value}'`);
139
- else if (typeof value === "boolean") metaProps.push(`${key}: ${value}`);
140
- else if (typeof value === "number") metaProps.push(`${key}: ${value}`);
141
- }
142
- return ` ${fn}: ${`{ ${metaProps.join(", ")} }`}`;
143
- }).join(",\n");
144
- return ` ${formatKey(module)}: {\n${fnEntries},\n }`;
145
- }).join(",\n");
146
- const metaContent = metaEntries ? `\n${metaEntries},\n` : "";
147
- const routesByPath = /* @__PURE__ */ new Map();
148
- for (const [key, route] of Object.entries(allHttpRoutes)) {
149
- const pathKey = `${route.path}:${route.method}`;
150
- const existing = routesByPath.get(pathKey) || [];
151
- existing.push({
152
- key,
153
- route
154
- });
155
- routesByPath.set(pathKey, existing);
156
- }
157
- const dedupedRoutes = {};
158
- for (const entries of routesByPath.values()) {
159
- const best = entries.reduce((a, b) => a.key.length >= b.key.length ? a : b);
160
- dedupedRoutes[best.key] = best.route;
161
- }
162
- const httpEntries = Object.entries(dedupedRoutes).sort(([a], [b]) => a.localeCompare(b)).map(([name, route]) => ` ${formatKey(name)}: { path: '${route.path}', method: '${route.method}' }`).join(",\n");
163
- const httpContent = httpEntries ? `\n${httpEntries},\n ` : "";
164
- const output = `// biome-ignore-all format: generated
165
- // This file is auto-generated by better-convex
166
- // Do not edit manually. Run \`better-convex codegen\` to regenerate.
167
-
168
- export const meta = {${metaContent ? `${metaContent} _http: {${httpContent}},\n` : `\n _http: {${httpContent}},\n`}} as const;
169
-
170
- export type Meta = typeof meta;
171
- `;
172
- const metaDir = path.dirname(outputFile);
173
- if (!fs.existsSync(metaDir)) fs.mkdirSync(metaDir, { recursive: true });
174
- fs.writeFileSync(outputFile, output);
175
- const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
176
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
177
- hour12: false,
178
- hour: "2-digit",
179
- minute: "2-digit",
180
- second: "2-digit"
181
- });
182
- if (!silent) if (debug) {
183
- console.info(`\n✅ Generated ${outputFile}`);
184
- console.info(` ${Object.keys(meta).length} modules, ${totalFunctions} functions`);
185
- } else console.info(`✔ ${time} Convex meta ready! (${elapsed}s)`);
186
- }
187
-
188
- //#endregion
189
- export { getConvexConfig as n, generateMeta as t };
@@ -1,17 +0,0 @@
1
- import { GenericActionCtx, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server";
2
-
3
- //#region src/server/context-utils.d.ts
4
- type GenericCtx<DataModel extends GenericDataModel = GenericDataModel> = GenericQueryCtx<DataModel> | GenericMutationCtx<DataModel> | GenericActionCtx<DataModel>;
5
- type RunMutationCtx<DataModel extends GenericDataModel> = (GenericMutationCtx<DataModel> | GenericActionCtx<DataModel>) & {
6
- runMutation: GenericMutationCtx<DataModel>['runMutation'];
7
- };
8
- declare const isQueryCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => ctx is GenericQueryCtx<DataModel>;
9
- declare const isMutationCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => ctx is GenericMutationCtx<DataModel>;
10
- declare const isActionCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => ctx is GenericActionCtx<DataModel>;
11
- declare const isRunMutationCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => ctx is RunMutationCtx<DataModel>;
12
- declare const requireQueryCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => GenericQueryCtx<DataModel>;
13
- declare const requireMutationCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => GenericMutationCtx<DataModel>;
14
- declare const requireActionCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => GenericActionCtx<DataModel>;
15
- declare const requireRunMutationCtx: <DataModel extends GenericDataModel>(ctx: GenericCtx<DataModel>) => RunMutationCtx<DataModel>;
16
- //#endregion
17
- export { isQueryCtx as a, requireMutationCtx as c, isMutationCtx as i, requireQueryCtx as l, RunMutationCtx as n, isRunMutationCtx as o, isActionCtx as r, requireActionCtx as s, GenericCtx as t, requireRunMutationCtx as u };
@@ -1,41 +0,0 @@
1
- //#region src/shared/meta-utils.ts
2
- /**
3
- * Get a function reference from the API object by traversing the path.
4
- */
5
- function getFuncRef(api, path) {
6
- let current = api;
7
- for (const key of path) if (current && typeof current === "object") current = current[key];
8
- else throw new Error(`Invalid path: ${path.join(".")}`);
9
- return current;
10
- }
11
- /**
12
- * Get function type from meta using path.
13
- * Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
14
- *
15
- * @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
16
- * @param meta - The meta object from codegen
17
- * @returns Function type or 'query' as default
18
- */
19
- function getFunctionType(path, meta) {
20
- if (path.length < 2) return "query";
21
- const fnName = path.at(-1);
22
- const fnType = meta[path.slice(0, -1).join("/")]?.[fnName]?.type;
23
- if (fnType === "query" || fnType === "mutation" || fnType === "action") return fnType;
24
- return "query";
25
- }
26
- /**
27
- * Get function metadata from meta using path.
28
- * Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
29
- *
30
- * @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
31
- * @param meta - The meta object from codegen
32
- * @returns Function metadata or undefined
33
- */
34
- function getFunctionMeta(path, meta) {
35
- if (path.length < 2) return;
36
- const fnName = path.at(-1);
37
- return meta[path.slice(0, -1).join("/")]?.[fnName];
38
- }
39
-
40
- //#endregion
41
- export { getFunctionMeta as n, getFunctionType as r, getFuncRef as t };