convex-zen 1.9.1 → 1.10.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.
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +195 -236
- package/dist/cli/generate.js.map +1 -1
- package/dist/client/helpers.d.ts +1 -1
- package/dist/client/helpers.js +1 -1
- package/dist/client/index.d.ts +13 -8
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +109 -13
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +48 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/{src/component/plugins/admin/_generated/api.ts → dist/component/_generated/api.js} +5 -24
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +357 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/{src/component/plugins/organization/_generated/dataModel.ts → dist/component/_generated/dataModel.d.ts} +4 -18
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/{src/component/plugins/admin/_generated/server.ts → dist/component/_generated/server.d.ts} +9 -44
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/core/_generated/api.d.ts +46 -0
- package/dist/component/core/_generated/api.d.ts.map +1 -0
- package/{src/component/plugins/organization/_generated/api.ts → dist/component/core/_generated/api.js} +5 -24
- package/dist/component/core/_generated/api.js.map +1 -0
- package/dist/component/core/_generated/component.d.ts +117 -0
- package/dist/component/core/_generated/component.d.ts.map +1 -0
- package/dist/component/core/_generated/component.js +11 -0
- package/dist/component/core/_generated/component.js.map +1 -0
- package/{src/component/plugins/admin/_generated/dataModel.ts → dist/component/core/_generated/dataModel.d.ts} +4 -18
- package/dist/component/core/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/core/_generated/dataModel.js +11 -0
- package/dist/component/core/_generated/dataModel.js.map +1 -0
- package/{src/component/plugins/organization/_generated/server.ts → dist/component/core/_generated/server.d.ts} +9 -44
- package/dist/component/core/_generated/server.d.ts.map +1 -0
- package/dist/component/core/_generated/server.js +78 -0
- package/dist/component/core/_generated/server.js.map +1 -0
- package/dist/component/core/convex.config.d.ts +3 -0
- package/dist/component/core/convex.config.d.ts.map +1 -0
- package/dist/component/core/convex.config.js +4 -0
- package/dist/component/core/convex.config.js.map +1 -0
- package/dist/component/core/core/users.d.ts +2 -0
- package/dist/component/core/core/users.d.ts.map +1 -0
- package/dist/component/core/core/users.js +2 -0
- package/dist/component/core/core/users.js.map +1 -0
- package/dist/component/core/core/verifications.d.ts +2 -0
- package/dist/component/core/core/verifications.d.ts.map +1 -0
- package/dist/component/core/core/verifications.js +2 -0
- package/dist/component/core/core/verifications.js.map +1 -0
- package/dist/component/core/gateway.d.ts +2 -0
- package/dist/component/core/gateway.d.ts.map +1 -0
- package/dist/component/core/gateway.js +2 -0
- package/dist/component/core/gateway.js.map +1 -0
- package/dist/component/core/providers/oauth.d.ts +2 -0
- package/dist/component/core/providers/oauth.d.ts.map +1 -0
- package/dist/component/core/providers/oauth.js +2 -0
- package/dist/component/core/providers/oauth.js.map +1 -0
- package/dist/component/core/schema.d.ts +2 -0
- package/dist/component/core/schema.d.ts.map +1 -0
- package/dist/component/core/schema.js +2 -0
- package/dist/component/core/schema.js.map +1 -0
- package/dist/component/core/sessions.d.ts +105 -0
- package/dist/component/core/sessions.d.ts.map +1 -0
- package/dist/component/core/sessions.js +201 -0
- package/dist/component/core/sessions.js.map +1 -0
- package/dist/component/core/users.d.ts +193 -0
- package/dist/component/core/users.d.ts.map +1 -0
- package/dist/component/core/users.js +237 -0
- package/dist/component/core/users.js.map +1 -0
- package/dist/component/core/verifications.d.ts +85 -0
- package/dist/component/core/verifications.d.ts.map +1 -0
- package/dist/component/core/verifications.js +133 -0
- package/dist/component/core/verifications.js.map +1 -0
- package/dist/component/gateway.d.ts +128 -0
- package/dist/component/gateway.d.ts.map +1 -0
- package/dist/component/gateway.js +162 -0
- package/dist/component/gateway.js.map +1 -0
- package/dist/component/index.d.ts +5 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +7 -0
- package/dist/component/index.js.map +1 -0
- package/dist/component/lib/crypto.d.ts +41 -0
- package/dist/component/lib/crypto.d.ts.map +1 -0
- package/dist/component/lib/crypto.js +152 -0
- package/dist/component/lib/crypto.js.map +1 -0
- package/dist/component/lib/internalApi.d.ts +58 -0
- package/dist/component/lib/internalApi.d.ts.map +1 -0
- package/dist/component/lib/internalApi.js +3 -0
- package/dist/component/lib/internalApi.js.map +1 -0
- package/dist/component/lib/object.d.ts +11 -0
- package/dist/component/lib/object.d.ts.map +1 -0
- package/dist/component/lib/object.js +4 -0
- package/dist/component/lib/object.js.map +1 -0
- package/dist/component/lib/rateLimit.d.ts +34 -0
- package/dist/component/lib/rateLimit.d.ts.map +1 -0
- package/dist/component/lib/rateLimit.js +96 -0
- package/dist/component/lib/rateLimit.js.map +1 -0
- package/dist/component/lib/validators.d.ts +31 -0
- package/dist/component/lib/validators.d.ts.map +1 -0
- package/dist/component/lib/validators.js +18 -0
- package/dist/component/lib/validators.js.map +1 -0
- package/dist/component/plugin.d.ts +59 -0
- package/dist/component/plugin.d.ts.map +1 -0
- package/dist/component/plugin.js +102 -0
- package/dist/component/plugin.js.map +1 -0
- package/dist/component/providers/emailPassword.d.ts +104 -0
- package/dist/component/providers/emailPassword.d.ts.map +1 -0
- package/dist/component/providers/emailPassword.js +363 -0
- package/dist/component/providers/emailPassword.js.map +1 -0
- package/dist/component/providers/oauth.d.ts +129 -0
- package/dist/component/providers/oauth.d.ts.map +1 -0
- package/dist/component/providers/oauth.js +349 -0
- package/dist/component/providers/oauth.js.map +1 -0
- package/dist/component/schema.d.ts +262 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +153 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/types.d.ts +81 -25
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -4
- package/dist/types.js.map +1 -1
- package/package.json +1 -33
- package/src/cli/generate.ts +284 -273
- package/src/client/helpers.ts +1 -1
- package/src/client/index.ts +202 -21
- package/src/component/_generated/api.ts +0 -4
- package/src/component/core/users.ts +15 -12
- package/src/component/gateway.ts +13 -10
- package/src/component/index.ts +9 -0
- package/src/component/lib/internalApi.ts +1 -45
- package/src/component/lib/object.ts +17 -0
- package/src/component/plugin.ts +362 -0
- package/src/component/providers/emailPassword.ts +3 -3
- package/src/component/providers/oauth.ts +51 -31
- package/src/types.ts +178 -33
- package/dist/client/plugins/admin.d.ts +0 -84
- package/dist/client/plugins/admin.d.ts.map +0 -1
- package/dist/client/plugins/admin.js +0 -161
- package/dist/client/plugins/admin.js.map +0 -1
- package/dist/client/plugins/organization.d.ts +0 -216
- package/dist/client/plugins/organization.d.ts.map +0 -1
- package/dist/client/plugins/organization.js +0 -634
- package/dist/client/plugins/organization.js.map +0 -1
- package/src/client/plugins/admin.ts +0 -265
- package/src/client/plugins/organization.ts +0 -1103
- package/src/component/plugins/admin/_generated/component.ts +0 -86
- package/src/component/plugins/admin/convex.config.ts +0 -5
- package/src/component/plugins/admin/gateway.ts +0 -105
- package/src/component/plugins/admin/schema.ts +0 -16
- package/src/component/plugins/admin.ts +0 -268
- package/src/component/plugins/organization/_generated/component.ts +0 -408
- package/src/component/plugins/organization/convex.config.ts +0 -5
- package/src/component/plugins/organization/gateway.ts +0 -626
- package/src/component/plugins/organization/schema.ts +0 -70
- package/src/component/plugins/organization.ts +0 -2111
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAs2CD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAySzB"}
|
package/dist/cli/generate.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { access, mkdir, readFile, readdir, rm, writeFile, } from "node:fs/promises";
|
|
1
|
+
import { access, mkdir, readFile, readdir, rm, stat, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { collectPluginGatewayMetadata } from "../component/plugin";
|
|
4
6
|
const GENERATED_MARKER = "// @generated by convex-zen generate. DO NOT EDIT.";
|
|
5
7
|
const RESERVED_CORE_FUNCTION_NAMES = new Set([
|
|
6
8
|
"getSession",
|
|
@@ -9,6 +11,7 @@ const RESERVED_CORE_FUNCTION_NAMES = new Set([
|
|
|
9
11
|
"plugin",
|
|
10
12
|
"core",
|
|
11
13
|
]);
|
|
14
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
12
15
|
function normalizeContent(content) {
|
|
13
16
|
const trimmed = content.trimEnd();
|
|
14
17
|
return trimmed.endsWith("\n") ? trimmed : `${trimmed}\n`;
|
|
@@ -22,6 +25,90 @@ async function fileExists(filePath) {
|
|
|
22
25
|
return false;
|
|
23
26
|
}
|
|
24
27
|
}
|
|
28
|
+
function splitPackageSpecifier(moduleSpecifier) {
|
|
29
|
+
if (moduleSpecifier.startsWith("@")) {
|
|
30
|
+
const [scope, name, ...rest] = moduleSpecifier.split("/");
|
|
31
|
+
return {
|
|
32
|
+
packageName: [scope, name].filter(Boolean).join("/"),
|
|
33
|
+
subpath: rest.join("/"),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const [name, ...rest] = moduleSpecifier.split("/");
|
|
37
|
+
return {
|
|
38
|
+
packageName: name ?? moduleSpecifier,
|
|
39
|
+
subpath: rest.join("/"),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function readExportTarget(exportsField, key) {
|
|
43
|
+
if (!exportsField || typeof exportsField !== "object") {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const record = exportsField;
|
|
47
|
+
const entry = record[key];
|
|
48
|
+
if (!entry) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (typeof entry === "string") {
|
|
52
|
+
return entry;
|
|
53
|
+
}
|
|
54
|
+
if (typeof entry === "object" && entry !== null) {
|
|
55
|
+
const importTarget = entry.import;
|
|
56
|
+
if (typeof importTarget === "string") {
|
|
57
|
+
return importTarget;
|
|
58
|
+
}
|
|
59
|
+
const defaultTarget = entry.default;
|
|
60
|
+
if (typeof defaultTarget === "string") {
|
|
61
|
+
return defaultTarget;
|
|
62
|
+
}
|
|
63
|
+
const typesTarget = entry.types;
|
|
64
|
+
if (typeof typesTarget === "string") {
|
|
65
|
+
return typesTarget;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
async function findWorkspacePackage(authSource, packageName) {
|
|
71
|
+
const workspaceRoot = (await findWorkspaceRoot(path.dirname(authSource.absolutePath))) ??
|
|
72
|
+
(await findWorkspaceRoot(path.dirname(fileURLToPath(import.meta.url))));
|
|
73
|
+
if (!workspaceRoot) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const packagesDir = path.join(workspaceRoot, "packages");
|
|
77
|
+
const packageDirs = await readdir(packagesDir).catch(() => []);
|
|
78
|
+
for (const packageDirName of packageDirs) {
|
|
79
|
+
const dir = path.join(packagesDir, packageDirName);
|
|
80
|
+
const packageJsonPath = path.join(dir, "package.json");
|
|
81
|
+
if (!(await fileExists(packageJsonPath))) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
85
|
+
if (packageJson.name !== packageName) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
dir,
|
|
90
|
+
name: packageName,
|
|
91
|
+
packageJson,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
async function resolveWorkspacePackageImport(authSource, moduleSpecifier) {
|
|
97
|
+
const { packageName, subpath } = splitPackageSpecifier(moduleSpecifier);
|
|
98
|
+
const workspacePackage = await findWorkspacePackage(authSource, packageName);
|
|
99
|
+
if (!workspacePackage) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const exportKey = subpath.length > 0 ? `./${subpath}` : ".";
|
|
103
|
+
const exportTarget = readExportTarget(workspacePackage.packageJson.exports, exportKey) ??
|
|
104
|
+
(subpath.length === 0 && typeof workspacePackage.packageJson.main === "string"
|
|
105
|
+
? workspacePackage.packageJson.main
|
|
106
|
+
: null);
|
|
107
|
+
if (!exportTarget) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return pathToFileURL(path.resolve(workspacePackage.dir, exportTarget)).href;
|
|
111
|
+
}
|
|
25
112
|
function isGeneratedFile(content) {
|
|
26
113
|
return content.startsWith(GENERATED_MARKER);
|
|
27
114
|
}
|
|
@@ -121,19 +208,71 @@ function toGeneratedImportPath(sourceFileAbsolutePath, targetFileAbsolutePath) {
|
|
|
121
208
|
const normalized = relativeImport.replace(/\\/g, "/").replace(/\.ts$/, "");
|
|
122
209
|
return normalized.startsWith(".") ? normalized : `./${normalized}`;
|
|
123
210
|
}
|
|
124
|
-
async function resolveGeneratedComponentImportPath(authSource, pluginModuleSpecifier,
|
|
125
|
-
if (!
|
|
126
|
-
return
|
|
211
|
+
async function resolveGeneratedComponentImportPath(authSource, pluginModuleSpecifier, pluginDefinition) {
|
|
212
|
+
if (!pluginModuleSpecifier.startsWith(".") && !path.isAbsolute(pluginModuleSpecifier)) {
|
|
213
|
+
return `${pluginModuleSpecifier}/convex.config`;
|
|
214
|
+
}
|
|
215
|
+
if (pluginModuleSpecifier.startsWith("convex-zen/plugins/")) {
|
|
216
|
+
return `${pluginModuleSpecifier}/convex.config`;
|
|
127
217
|
}
|
|
128
|
-
const pluginModulePath = pluginModuleSpecifier
|
|
129
|
-
? path.resolve(path.dirname(authSource.absolutePath), pluginModuleSpecifier)
|
|
130
|
-
: null;
|
|
218
|
+
const pluginModulePath = await resolvePluginModulePath(authSource, pluginModuleSpecifier);
|
|
131
219
|
if (!pluginModulePath) {
|
|
132
|
-
|
|
220
|
+
throw new Error(`Could not resolve plugin module path for "${pluginDefinition.id}" from "${pluginModuleSpecifier}".`);
|
|
133
221
|
}
|
|
134
|
-
|
|
222
|
+
if (pluginModulePath.includes(`${path.sep}src${path.sep}client${path.sep}plugins${path.sep}`) ||
|
|
223
|
+
pluginModulePath.includes(`${path.sep}src${path.sep}plugins${path.sep}`)) {
|
|
224
|
+
return `convex-zen/plugins/${pluginDefinition.id}/convex.config`;
|
|
225
|
+
}
|
|
226
|
+
const componentAbsolutePath = path.resolve(path.dirname(pluginModulePath), "convex.config.ts");
|
|
135
227
|
return toGeneratedImportPath(path.join(path.dirname(authSource.absolutePath), "zen", "component", "convex.config.ts"), componentAbsolutePath);
|
|
136
228
|
}
|
|
229
|
+
async function resolveGatewaySourcePath(authSource, pluginModuleSpecifier, pluginDefinition) {
|
|
230
|
+
if (!pluginModuleSpecifier.startsWith(".") && !path.isAbsolute(pluginModuleSpecifier)) {
|
|
231
|
+
return `${pluginModuleSpecifier}/gateway`;
|
|
232
|
+
}
|
|
233
|
+
if (pluginModuleSpecifier.startsWith("convex-zen/plugins/")) {
|
|
234
|
+
return `${pluginModuleSpecifier}/gateway`;
|
|
235
|
+
}
|
|
236
|
+
const pluginModulePath = await resolvePluginModulePath(authSource, pluginModuleSpecifier);
|
|
237
|
+
if (!pluginModulePath) {
|
|
238
|
+
throw new Error(`Could not resolve plugin module path for "${pluginDefinition.id}" from "${pluginModuleSpecifier}".`);
|
|
239
|
+
}
|
|
240
|
+
if (pluginModulePath.includes(`${path.sep}src${path.sep}client${path.sep}plugins${path.sep}`) ||
|
|
241
|
+
pluginModulePath.includes(`${path.sep}src${path.sep}plugins${path.sep}`)) {
|
|
242
|
+
return `convex-zen/plugins/${pluginDefinition.id}/gateway`;
|
|
243
|
+
}
|
|
244
|
+
return path.resolve(path.dirname(pluginModulePath), "gateway.ts");
|
|
245
|
+
}
|
|
246
|
+
async function resolvePluginModulePath(authSource, pluginModuleSpecifier) {
|
|
247
|
+
if (path.isAbsolute(pluginModuleSpecifier)) {
|
|
248
|
+
return pluginModuleSpecifier;
|
|
249
|
+
}
|
|
250
|
+
if (!pluginModuleSpecifier.startsWith(".")) {
|
|
251
|
+
if (pluginModuleSpecifier === "convex-zen") {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const moduleSpecifier = await resolveImportSpecifier(authSource, pluginModuleSpecifier);
|
|
255
|
+
return moduleSpecifier.startsWith("file:")
|
|
256
|
+
? fileURLToPath(moduleSpecifier)
|
|
257
|
+
: null;
|
|
258
|
+
}
|
|
259
|
+
const resolved = path.resolve(path.dirname(authSource.absolutePath), pluginModuleSpecifier);
|
|
260
|
+
if (await fileExists(resolved)) {
|
|
261
|
+
const resolvedStats = await stat(resolved);
|
|
262
|
+
if (resolvedStats.isFile()) {
|
|
263
|
+
return resolved;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const indexPath = path.join(resolved, "index.ts");
|
|
267
|
+
if (await fileExists(indexPath)) {
|
|
268
|
+
return indexPath;
|
|
269
|
+
}
|
|
270
|
+
const directTsPath = `${resolved}.ts`;
|
|
271
|
+
if (await fileExists(directTsPath)) {
|
|
272
|
+
return directTsPath;
|
|
273
|
+
}
|
|
274
|
+
return resolved;
|
|
275
|
+
}
|
|
137
276
|
async function resolveImportSpecifier(authSource, moduleSpecifier) {
|
|
138
277
|
if (moduleSpecifier.startsWith(".")) {
|
|
139
278
|
return pathToFileURL(path.resolve(path.dirname(authSource.absolutePath), moduleSpecifier)).href;
|
|
@@ -155,13 +294,25 @@ async function resolveImportSpecifier(authSource, moduleSpecifier) {
|
|
|
155
294
|
: subpath === "core/convex.config"
|
|
156
295
|
? path.join(workspaceRoot, "packages", "convex-zen", "src", "component", "core", "convex.config.ts")
|
|
157
296
|
: subpath.startsWith("plugins/") && subpath.endsWith("/convex.config")
|
|
158
|
-
? path.join(workspaceRoot, "packages", "convex-zen", "src", "
|
|
159
|
-
:
|
|
297
|
+
? path.join(workspaceRoot, "packages", "convex-zen", "src", "plugins", subpath.replace(/^plugins\//, "").replace(/\/convex\.config$/, ""), "convex.config.ts")
|
|
298
|
+
: subpath.startsWith("plugins/") && subpath.endsWith("/gateway")
|
|
299
|
+
? path.join(workspaceRoot, "packages", "convex-zen", "src", "plugins", subpath.replace(/^plugins\//, "").replace(/\/gateway$/, ""), "gateway.ts")
|
|
300
|
+
: path.join(workspaceRoot, "packages", "convex-zen", "src", "client", `${subpath}.ts`);
|
|
160
301
|
if (await fileExists(mapped)) {
|
|
161
302
|
return pathToFileURL(mapped).href;
|
|
162
303
|
}
|
|
163
304
|
}
|
|
164
305
|
}
|
|
306
|
+
if (!moduleSpecifier.startsWith(".")) {
|
|
307
|
+
const workspaceImport = await resolveWorkspacePackageImport(authSource, moduleSpecifier);
|
|
308
|
+
if (workspaceImport) {
|
|
309
|
+
return workspaceImport;
|
|
310
|
+
}
|
|
311
|
+
const resolved = nodeRequire.resolve(moduleSpecifier, {
|
|
312
|
+
paths: [path.dirname(authSource.absolutePath)],
|
|
313
|
+
});
|
|
314
|
+
return pathToFileURL(resolved).href;
|
|
315
|
+
}
|
|
165
316
|
return moduleSpecifier;
|
|
166
317
|
}
|
|
167
318
|
async function findWorkspaceRoot(startDir) {
|
|
@@ -188,10 +339,13 @@ async function loadPluginDefinitions(authSource, authSourceContents) {
|
|
|
188
339
|
throw new Error(`Could not resolve plugin factory "${factoryId}" from ${authSource.relativePath}.`);
|
|
189
340
|
}
|
|
190
341
|
const definition = await importPluginDefinition(authSource, binding);
|
|
342
|
+
const gatewayFunctions = collectPluginGatewayMetadata(definition.gateway);
|
|
191
343
|
definitions.push({
|
|
192
344
|
definition,
|
|
193
|
-
componentImportPath: await resolveGeneratedComponentImportPath(authSource, binding.moduleSpecifier, definition
|
|
194
|
-
|
|
345
|
+
componentImportPath: await resolveGeneratedComponentImportPath(authSource, binding.moduleSpecifier, definition),
|
|
346
|
+
gatewaySourcePath: await resolveGatewaySourcePath(authSource, binding.moduleSpecifier, definition),
|
|
347
|
+
childName: `${definition.id}Component`,
|
|
348
|
+
gatewayFunctions,
|
|
195
349
|
});
|
|
196
350
|
}
|
|
197
351
|
return definitions;
|
|
@@ -575,113 +729,22 @@ export const getUserById = query({
|
|
|
575
729
|
${oauthExports}
|
|
576
730
|
`);
|
|
577
731
|
}
|
|
578
|
-
function
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
? [" actorEmail: v.optional(v.string()),"]
|
|
583
|
-
: []),
|
|
584
|
-
];
|
|
585
|
-
if (argsSource.trim() === "{}") {
|
|
586
|
-
return `{\n${actorFields.join("\n")}\n }`;
|
|
587
|
-
}
|
|
588
|
-
return argsSource.replace("{", `{\n${actorFields.join("\n")}\n`);
|
|
732
|
+
function resolveGatewayImportPathForGeneratedFile(generatedFileAbsolutePath, gatewaySourcePath) {
|
|
733
|
+
return gatewaySourcePath.startsWith("/")
|
|
734
|
+
? toGeneratedImportPath(generatedFileAbsolutePath, gatewaySourcePath)
|
|
735
|
+
: gatewaySourcePath;
|
|
589
736
|
}
|
|
590
|
-
function
|
|
737
|
+
function renderPluginFacadeFile(options) {
|
|
591
738
|
const pluginName = options.pluginDefinition.id;
|
|
592
|
-
const
|
|
593
|
-
if (!publicFunctions) {
|
|
594
|
-
throw new Error(`Plugin "${pluginName}" is missing public function metadata.`);
|
|
595
|
-
}
|
|
596
|
-
const kinds = new Set(Object.values(publicFunctions.functions).map((fn) => fn.kind));
|
|
739
|
+
const kinds = new Set(Object.values(options.gatewayFunctions).map((fn) => fn.kind));
|
|
597
740
|
const serverImports = [...kinds].sort().join(", ");
|
|
598
|
-
const
|
|
599
|
-
const preamble = publicFunctions.preambleSource
|
|
600
|
-
? `${publicFunctions.preambleSource}\n\n`
|
|
601
|
-
: "";
|
|
602
|
-
const actorHelper = needsActorHelper
|
|
603
|
-
? `async function requireActorUserId(ctx: { auth: { getUserIdentity: () => Promise<{ subject?: string } | null> } }): Promise<string> {
|
|
604
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
605
|
-
const actorUserId = identity?.subject;
|
|
606
|
-
if (!actorUserId) {
|
|
607
|
-
throw new Error("Unauthorized: missing identity subject");
|
|
608
|
-
}
|
|
609
|
-
return actorUserId;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
`
|
|
613
|
-
: "";
|
|
614
|
-
const actorEmailMethods = pluginName === "organization"
|
|
615
|
-
? new Set([
|
|
616
|
-
"listIncomingInvitations",
|
|
617
|
-
"acceptInvitation",
|
|
618
|
-
"acceptIncomingInvitation",
|
|
619
|
-
"declineIncomingInvitation",
|
|
620
|
-
])
|
|
621
|
-
: new Set();
|
|
622
|
-
const actorEmailHelper = actorEmailMethods.size > 0
|
|
623
|
-
? `async function resolveActorEmail(ctx: unknown): Promise<string | undefined> {
|
|
624
|
-
const actor = await auth.user.safeGet(ctx as { runQuery(fn: unknown, args: Record<string, unknown>): Promise<unknown> });
|
|
625
|
-
return actor?.email;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
`
|
|
629
|
-
: "";
|
|
630
|
-
const functionSource = Object.entries(publicFunctions.functions)
|
|
741
|
+
const functionSource = Object.entries(options.gatewayFunctions)
|
|
631
742
|
.map(([functionName, fn]) => {
|
|
632
|
-
const runtimeAccess = `auth.plugins.${pluginName}`;
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
? addInternalActorFieldsToArgsSource(fn.argsSource, {
|
|
636
|
-
includeActorEmail: actorEmailMethods.has(functionName),
|
|
637
|
-
})
|
|
638
|
-
: fn.argsSource;
|
|
639
|
-
if (fn.auth === "public") {
|
|
640
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
641
|
-
args: ${argsSource},
|
|
642
|
-
handler: async (ctx, args) => {
|
|
643
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, args as any);
|
|
644
|
-
},
|
|
645
|
-
});`;
|
|
646
|
-
}
|
|
647
|
-
if (fn.auth === "optionalActor") {
|
|
648
|
-
const optionalActorEmail = actorEmailMethods.has(functionName)
|
|
649
|
-
? ` const actorEmail = await resolveActorEmail(ctx);\n`
|
|
650
|
-
: "";
|
|
651
|
-
const optionalActorEmailSpread = actorEmailMethods.has(functionName)
|
|
652
|
-
? ` ...(actorEmail ? { actorEmail } : {}),\n`
|
|
653
|
-
: "";
|
|
654
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
655
|
-
args: ${argsSource},
|
|
656
|
-
handler: async (ctx, args) => {
|
|
657
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
658
|
-
const actorUserId = identity?.subject;
|
|
659
|
-
if (!actorUserId) {
|
|
660
|
-
return false;
|
|
661
|
-
}
|
|
662
|
-
${optionalActorEmail} const { actorUserId: _ignoredActorUserId, ...inputArgs } = args as Record<string, unknown>;
|
|
663
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, {
|
|
664
|
-
...inputArgs,
|
|
665
|
-
actorUserId,
|
|
666
|
-
${optionalActorEmailSpread} } as any);
|
|
667
|
-
},
|
|
668
|
-
});`;
|
|
669
|
-
}
|
|
670
|
-
const actorEmailResolution = actorEmailMethods.has(functionName)
|
|
671
|
-
? ` const actorEmail = await resolveActorEmail(ctx);\n`
|
|
672
|
-
: "";
|
|
673
|
-
const actorEmailSpread = actorEmailMethods.has(functionName)
|
|
674
|
-
? ` ...(actorEmail ? { actorEmail } : {}),\n`
|
|
675
|
-
: "";
|
|
676
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
677
|
-
args: ${argsSource},
|
|
743
|
+
const runtimeAccess = `auth.plugins.${pluginName}.${functionName}`;
|
|
744
|
+
return `export const ${functionName} = ${fn.kind}({
|
|
745
|
+
args: getPublicPluginFunctionArgs(pluginGateway.${functionName}, ${JSON.stringify(functionName)}),
|
|
678
746
|
handler: async (ctx, args) => {
|
|
679
|
-
|
|
680
|
-
${actorEmailResolution} const { actorUserId: _ignoredActorUserId, ...inputArgs } = args as Record<string, unknown>;
|
|
681
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, {
|
|
682
|
-
...inputArgs,
|
|
683
|
-
actorUserId,
|
|
684
|
-
${actorEmailSpread} } as any);
|
|
747
|
+
return ${runtimeAccess}(ctx, args);
|
|
685
748
|
},
|
|
686
749
|
});`;
|
|
687
750
|
})
|
|
@@ -691,11 +754,12 @@ ${actorEmailSpread} } as any);
|
|
|
691
754
|
? `import { auth } from ${JSON.stringify(options.runtimeImportPath)};`
|
|
692
755
|
: `import { ${runtimeImportName} as auth } from ${JSON.stringify(options.runtimeImportPath)};`;
|
|
693
756
|
return normalizeContent(`${GENERATED_MARKER}
|
|
694
|
-
import { v } from "convex/values";
|
|
695
757
|
import { ${serverImports} } from ${JSON.stringify(options.serverImportPath)};
|
|
758
|
+
import { getPublicPluginFunctionArgs } from "convex-zen/component";
|
|
759
|
+
import * as pluginGateway from ${JSON.stringify(options.gatewayImportPath)};
|
|
696
760
|
${runtimeImport}
|
|
697
761
|
|
|
698
|
-
${
|
|
762
|
+
${functionSource}
|
|
699
763
|
`);
|
|
700
764
|
}
|
|
701
765
|
function renderCoreFile(options) {
|
|
@@ -881,117 +945,6 @@ export const currentUser = query({
|
|
|
881
945
|
${oauthExports}
|
|
882
946
|
`);
|
|
883
947
|
}
|
|
884
|
-
function renderPluginFile(options) {
|
|
885
|
-
const pluginName = options.pluginDefinition.id;
|
|
886
|
-
const publicFunctions = options.pluginDefinition.publicFunctions;
|
|
887
|
-
if (!publicFunctions) {
|
|
888
|
-
throw new Error(`Plugin "${pluginName}" is missing public function metadata.`);
|
|
889
|
-
}
|
|
890
|
-
const kinds = new Set(Object.values(publicFunctions.functions).map((fn) => fn.kind));
|
|
891
|
-
const serverImports = [...kinds].sort().join(", ");
|
|
892
|
-
const needsActorHelper = Object.values(publicFunctions.functions).some((fn) => fn.auth === "actor" || fn.auth === "optionalActor");
|
|
893
|
-
const preamble = publicFunctions.preambleSource
|
|
894
|
-
? `${publicFunctions.preambleSource}\n\n`
|
|
895
|
-
: "";
|
|
896
|
-
const actorHelper = needsActorHelper
|
|
897
|
-
? `async function requireActorUserId(ctx: { auth: { getUserIdentity: () => Promise<{ subject?: string } | null> } }): Promise<string> {
|
|
898
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
899
|
-
const actorUserId = identity?.subject;
|
|
900
|
-
if (!actorUserId) {
|
|
901
|
-
throw new Error("Unauthorized: missing identity subject");
|
|
902
|
-
}
|
|
903
|
-
return actorUserId;
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
`
|
|
907
|
-
: "";
|
|
908
|
-
const actorEmailMethods = pluginName === "organization"
|
|
909
|
-
? new Set([
|
|
910
|
-
"listIncomingInvitations",
|
|
911
|
-
"acceptInvitation",
|
|
912
|
-
"acceptIncomingInvitation",
|
|
913
|
-
"declineIncomingInvitation",
|
|
914
|
-
])
|
|
915
|
-
: new Set();
|
|
916
|
-
const actorEmailHelper = actorEmailMethods.size > 0
|
|
917
|
-
? `async function resolveActorEmail(ctx: unknown): Promise<string | undefined> {
|
|
918
|
-
const actor = await auth.user.safeGet(ctx as { runQuery(fn: unknown, args: Record<string, unknown>): Promise<unknown> });
|
|
919
|
-
return actor?.email;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
`
|
|
923
|
-
: "";
|
|
924
|
-
const functionSource = Object.entries(publicFunctions.functions)
|
|
925
|
-
.map(([functionName, fn]) => {
|
|
926
|
-
const runtimeAccess = `auth.plugins.${pluginName}`;
|
|
927
|
-
const kindFactory = fn.kind;
|
|
928
|
-
const argsSource = fn.auth === "actor" || fn.auth === "optionalActor"
|
|
929
|
-
? addInternalActorFieldsToArgsSource(fn.argsSource, {
|
|
930
|
-
includeActorEmail: actorEmailMethods.has(functionName),
|
|
931
|
-
})
|
|
932
|
-
: fn.argsSource;
|
|
933
|
-
if (fn.auth === "public") {
|
|
934
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
935
|
-
args: ${argsSource},
|
|
936
|
-
handler: async (ctx, args) => {
|
|
937
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, args as any);
|
|
938
|
-
},
|
|
939
|
-
});`;
|
|
940
|
-
}
|
|
941
|
-
if (fn.auth === "optionalActor") {
|
|
942
|
-
const optionalActorEmail = actorEmailMethods.has(functionName)
|
|
943
|
-
? `
|
|
944
|
-
const actorEmail = await resolveActorEmail(ctx);`
|
|
945
|
-
: "";
|
|
946
|
-
const optionalActorEmailSpread = actorEmailMethods.has(functionName)
|
|
947
|
-
? `
|
|
948
|
-
...(actorEmail ? { actorEmail } : {}),`
|
|
949
|
-
: "";
|
|
950
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
951
|
-
args: ${argsSource},
|
|
952
|
-
handler: async (ctx, args) => {
|
|
953
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
954
|
-
const actorUserId = identity?.subject;
|
|
955
|
-
if (!actorUserId) {
|
|
956
|
-
return false;
|
|
957
|
-
}
|
|
958
|
-
${optionalActorEmail}
|
|
959
|
-
const { actorUserId: _ignoredActorUserId, ...inputArgs } = args as Record<string, unknown>;
|
|
960
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, {
|
|
961
|
-
...inputArgs,
|
|
962
|
-
actorUserId,
|
|
963
|
-
${optionalActorEmailSpread}
|
|
964
|
-
} as any);
|
|
965
|
-
},
|
|
966
|
-
});`;
|
|
967
|
-
}
|
|
968
|
-
const actorEmailResolution = actorEmailMethods.has(functionName)
|
|
969
|
-
? ` const actorEmail = await resolveActorEmail(ctx);\n`
|
|
970
|
-
: "";
|
|
971
|
-
const actorEmailSpread = actorEmailMethods.has(functionName)
|
|
972
|
-
? ` ...(actorEmail ? { actorEmail } : {}),\n`
|
|
973
|
-
: "";
|
|
974
|
-
return `export const ${functionName} = ${kindFactory}({
|
|
975
|
-
args: ${argsSource},
|
|
976
|
-
handler: async (ctx, args) => {
|
|
977
|
-
const actorUserId = await requireActorUserId(ctx);
|
|
978
|
-
${actorEmailResolution} const { actorUserId: _ignoredActorUserId, ...inputArgs } = args as Record<string, unknown>;
|
|
979
|
-
return ${runtimeAccess}.${fn.runtimeMethod}(ctx, {
|
|
980
|
-
...inputArgs,
|
|
981
|
-
actorUserId,
|
|
982
|
-
${actorEmailSpread} } as any);
|
|
983
|
-
},
|
|
984
|
-
});`;
|
|
985
|
-
})
|
|
986
|
-
.join("\n\n");
|
|
987
|
-
return normalizeContent(`${GENERATED_MARKER}
|
|
988
|
-
import { v } from "convex/values";
|
|
989
|
-
import { ${serverImports} } from "../../_generated/server";
|
|
990
|
-
import { auth } from "../_generated/auth";
|
|
991
|
-
|
|
992
|
-
${actorHelper}${actorEmailHelper}${preamble}${functionSource}
|
|
993
|
-
`);
|
|
994
|
-
}
|
|
995
948
|
function parseFunctionKinds(source) {
|
|
996
949
|
const result = {};
|
|
997
950
|
const pattern = /export\s+const\s+([A-Za-z0-9_]+)\s*=\s*(query|mutation|action)\s*\(/g;
|
|
@@ -1244,24 +1197,30 @@ export async function generateAuthFunctions(options) {
|
|
|
1244
1197
|
const generatedPluginSources = new Map();
|
|
1245
1198
|
const coreMeta = parseFunctionKinds(coreContent);
|
|
1246
1199
|
for (const pluginDefinition of pluginDefinitions) {
|
|
1247
|
-
const
|
|
1200
|
+
const pluginAbsolutePath = path.join(pluginDir, `${pluginDefinition.definition.id}.ts`);
|
|
1201
|
+
const pluginContent = renderPluginFacadeFile({
|
|
1248
1202
|
pluginDefinition: pluginDefinition.definition,
|
|
1203
|
+
gatewayFunctions: pluginDefinition.gatewayFunctions,
|
|
1204
|
+
gatewayImportPath: resolveGatewayImportPathForGeneratedFile(pluginAbsolutePath, pluginDefinition.gatewaySourcePath),
|
|
1249
1205
|
serverImportPath: "../../_generated/server",
|
|
1250
1206
|
runtimeImportPath: "../_generated/auth",
|
|
1251
1207
|
});
|
|
1252
1208
|
filesToGenerate.push({
|
|
1253
|
-
absolutePath:
|
|
1209
|
+
absolutePath: pluginAbsolutePath,
|
|
1254
1210
|
relativePath: path.join("convex", "zen", "plugin", `${pluginDefinition.definition.id}.ts`),
|
|
1255
1211
|
content: pluginContent,
|
|
1256
1212
|
});
|
|
1257
1213
|
generatedPluginSources.set(pluginDefinition.definition.id, pluginContent);
|
|
1258
|
-
const
|
|
1214
|
+
const componentGatewayAbsolutePath = path.join(componentDir, pluginDefinition.definition.id, "gateway.ts");
|
|
1215
|
+
const zenPluginContent = renderPluginFacadeFile({
|
|
1259
1216
|
pluginDefinition: pluginDefinition.definition,
|
|
1217
|
+
gatewayFunctions: pluginDefinition.gatewayFunctions,
|
|
1218
|
+
gatewayImportPath: resolveGatewayImportPathForGeneratedFile(componentGatewayAbsolutePath, pluginDefinition.gatewaySourcePath),
|
|
1260
1219
|
serverImportPath: "../_generated/server",
|
|
1261
1220
|
runtimeImportPath: "../_runtime",
|
|
1262
1221
|
});
|
|
1263
1222
|
filesToGenerate.push({
|
|
1264
|
-
absolutePath:
|
|
1223
|
+
absolutePath: componentGatewayAbsolutePath,
|
|
1265
1224
|
relativePath: path.join("convex", "zen", "component", pluginDefinition.definition.id, "gateway.ts"),
|
|
1266
1225
|
content: zenPluginContent,
|
|
1267
1226
|
});
|
|
@@ -1271,10 +1230,10 @@ export async function generateAuthFunctions(options) {
|
|
|
1271
1230
|
}
|
|
1272
1231
|
await deleteGeneratedFileIfExists(path.join(zenDir, "admin.ts"), path.join("convex", "zen", "admin.ts"), options, result);
|
|
1273
1232
|
const pluginMeta = {};
|
|
1274
|
-
for (const
|
|
1275
|
-
const kinds =
|
|
1233
|
+
for (const pluginDefinition of pluginDefinitions) {
|
|
1234
|
+
const kinds = Object.fromEntries(Object.entries(pluginDefinition.gatewayFunctions).map(([functionName, metadata]) => [functionName, metadata.kind]));
|
|
1276
1235
|
if (Object.keys(kinds).length > 0) {
|
|
1277
|
-
pluginMeta[
|
|
1236
|
+
pluginMeta[pluginDefinition.definition.id] = kinds;
|
|
1278
1237
|
}
|
|
1279
1238
|
}
|
|
1280
1239
|
if (await fileExists(pluginDir)) {
|