test
This commit is contained in:
46
component/_generated/api.ts
Normal file
46
component/_generated/api.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated `api` utility.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type {
|
||||
ApiFromModules,
|
||||
FilterApi,
|
||||
FunctionReference,
|
||||
} from "convex/server";
|
||||
import { anyApi, componentsGeneric } from "convex/server";
|
||||
|
||||
const fullApi: ApiFromModules<{}> = anyApi as any;
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's public API.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* const myFunctionReference = api.myModule.myFunction;
|
||||
* ```
|
||||
*/
|
||||
export const api: FilterApi<
|
||||
typeof fullApi,
|
||||
FunctionReference<any, "public">
|
||||
> = anyApi as any;
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's internal API.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* const myFunctionReference = internal.myModule.myFunction;
|
||||
* ```
|
||||
*/
|
||||
export const internal: FilterApi<
|
||||
typeof fullApi,
|
||||
FunctionReference<any, "internal">
|
||||
> = anyApi as any;
|
||||
|
||||
export const components = componentsGeneric() as unknown as {};
|
||||
25
component/_generated/component.ts
Normal file
25
component/_generated/component.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated `ComponentApi` utility.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type { FunctionReference } from "convex/server";
|
||||
|
||||
/**
|
||||
* A utility for referencing a Convex component's exposed API.
|
||||
*
|
||||
* Useful when expecting a parameter like `components.myComponent`.
|
||||
* Usage:
|
||||
* ```ts
|
||||
* async function myFunction(ctx: QueryCtx, component: ComponentApi) {
|
||||
* return ctx.runQuery(component.someFile.someQuery, { ...args });
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export type ComponentApi<Name extends string | undefined = string | undefined> =
|
||||
{};
|
||||
60
component/_generated/dataModel.ts
Normal file
60
component/_generated/dataModel.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated data model types.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type {
|
||||
DataModelFromSchemaDefinition,
|
||||
DocumentByName,
|
||||
TableNamesInDataModel,
|
||||
SystemTableNames,
|
||||
} from "convex/server";
|
||||
import type { GenericId } from "convex/values";
|
||||
import schema from "../schema.js";
|
||||
|
||||
/**
|
||||
* The names of all of your Convex tables.
|
||||
*/
|
||||
export type TableNames = TableNamesInDataModel<DataModel>;
|
||||
|
||||
/**
|
||||
* The type of a document stored in Convex.
|
||||
*
|
||||
* @typeParam TableName - A string literal type of the table name (like "users").
|
||||
*/
|
||||
export type Doc<TableName extends TableNames> = DocumentByName<
|
||||
DataModel,
|
||||
TableName
|
||||
>;
|
||||
|
||||
/**
|
||||
* An identifier for a document in Convex.
|
||||
*
|
||||
* Convex documents are uniquely identified by their `Id`, which is accessible
|
||||
* on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids).
|
||||
*
|
||||
* Documents can be loaded using `db.get(tableName, id)` in query and mutation functions.
|
||||
*
|
||||
* IDs are just strings at runtime, but this type can be used to distinguish them from other
|
||||
* strings when type checking.
|
||||
*
|
||||
* @typeParam TableName - A string literal type of the table name (like "users").
|
||||
*/
|
||||
export type Id<TableName extends TableNames | SystemTableNames> =
|
||||
GenericId<TableName>;
|
||||
|
||||
/**
|
||||
* A type describing your Convex data model.
|
||||
*
|
||||
* This type includes information about what tables you have, the type of
|
||||
* documents stored in those tables, and the indexes defined on them.
|
||||
*
|
||||
* This type is used to parameterize methods like `queryGeneric` and
|
||||
* `mutationGeneric` to make them type-safe.
|
||||
*/
|
||||
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;
|
||||
156
component/_generated/server.ts
Normal file
156
component/_generated/server.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated utilities for implementing server-side Convex query and mutation functions.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type {
|
||||
ActionBuilder,
|
||||
HttpActionBuilder,
|
||||
MutationBuilder,
|
||||
QueryBuilder,
|
||||
GenericActionCtx,
|
||||
GenericMutationCtx,
|
||||
GenericQueryCtx,
|
||||
GenericDatabaseReader,
|
||||
GenericDatabaseWriter,
|
||||
} from "convex/server";
|
||||
import {
|
||||
actionGeneric,
|
||||
httpActionGeneric,
|
||||
queryGeneric,
|
||||
mutationGeneric,
|
||||
internalActionGeneric,
|
||||
internalMutationGeneric,
|
||||
internalQueryGeneric,
|
||||
} from "convex/server";
|
||||
import type { DataModel } from "./dataModel.js";
|
||||
|
||||
/**
|
||||
* Define a query in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to read your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const query: QueryBuilder<DataModel, "public"> = queryGeneric;
|
||||
|
||||
/**
|
||||
* Define a query that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to read from your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalQuery: QueryBuilder<DataModel, "internal"> =
|
||||
internalQueryGeneric;
|
||||
|
||||
/**
|
||||
* Define a mutation in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to modify your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const mutation: MutationBuilder<DataModel, "public"> = mutationGeneric;
|
||||
|
||||
/**
|
||||
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to modify your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalMutation: MutationBuilder<DataModel, "internal"> =
|
||||
internalMutationGeneric;
|
||||
|
||||
/**
|
||||
* Define an action in this Convex app's public API.
|
||||
*
|
||||
* An action is a function which can execute any JavaScript code, including non-deterministic
|
||||
* code and code with side-effects, like calling third-party services.
|
||||
* They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
|
||||
* They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
|
||||
*
|
||||
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const action: ActionBuilder<DataModel, "public"> = actionGeneric;
|
||||
|
||||
/**
|
||||
* Define an action that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalAction: ActionBuilder<DataModel, "internal"> =
|
||||
internalActionGeneric;
|
||||
|
||||
/**
|
||||
* Define an HTTP action.
|
||||
*
|
||||
* The wrapped function will be used to respond to HTTP requests received
|
||||
* by a Convex deployment if the requests matches the path and method where
|
||||
* this action is routed. Be sure to route your httpAction in `convex/http.js`.
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument
|
||||
* and a Fetch API `Request` object as its second.
|
||||
* @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
|
||||
*/
|
||||
export const httpAction: HttpActionBuilder = httpActionGeneric;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex query functions.
|
||||
*
|
||||
* The query context is passed as the first argument to any Convex query
|
||||
* function run on the server.
|
||||
*
|
||||
* If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead.
|
||||
*/
|
||||
export type QueryCtx = GenericQueryCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex mutation functions.
|
||||
*
|
||||
* The mutation context is passed as the first argument to any Convex mutation
|
||||
* function run on the server.
|
||||
*
|
||||
* If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead.
|
||||
*/
|
||||
export type MutationCtx = GenericMutationCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex action functions.
|
||||
*
|
||||
* The action context is passed as the first argument to any Convex action
|
||||
* function run on the server.
|
||||
*/
|
||||
export type ActionCtx = GenericActionCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* An interface to read from the database within Convex query functions.
|
||||
*
|
||||
* The two entry points are {@link DatabaseReader.get}, which fetches a single
|
||||
* document by its {@link Id}, or {@link DatabaseReader.query}, which starts
|
||||
* building a query.
|
||||
*/
|
||||
export type DatabaseReader = GenericDatabaseReader<DataModel>;
|
||||
|
||||
/**
|
||||
* An interface to read from and write to the database within Convex mutation
|
||||
* functions.
|
||||
*
|
||||
* Convex guarantees that all writes within a single mutation are
|
||||
* executed atomically, so you never have to worry about partial writes leaving
|
||||
* your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control)
|
||||
* for the guarantees Convex provides your functions.
|
||||
*/
|
||||
export type DatabaseWriter = GenericDatabaseWriter<DataModel>;
|
||||
5
component/convex.config.ts
Normal file
5
component/convex.config.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
'use node';
|
||||
import { defineComponent } from "convex/server";
|
||||
const component = defineComponent("component");
|
||||
|
||||
export default component;
|
||||
9
component/schema.ts
Normal file
9
component/schema.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { defineSchema, defineTable } from "convex/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
// Define a messages table with an index.
|
||||
export default defineSchema({
|
||||
// test2: defineTable({
|
||||
// title: v.string(),
|
||||
// }),
|
||||
});
|
||||
26
component/test2.ts
Normal file
26
component/test2.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// import { query, mutation, action } from "./_generated/server";
|
||||
// import { v } from "convex/values";
|
||||
// export const get = query({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// const auth = await ctx.auth.getUserIdentity();
|
||||
// console.log("Query test2 called, auth:", auth);
|
||||
// if (auth) {
|
||||
// console.log("Authenticated user ID:", auth.subject);
|
||||
// }
|
||||
// return await ctx.db.query("test2").collect();
|
||||
// },
|
||||
// });
|
||||
|
||||
// export const get2 = query({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// const auth = await ctx.auth.getUserIdentity();
|
||||
// console.log("Query test2 called, auth:", auth);
|
||||
// if (auth) {
|
||||
// console.log("Authenticated user ID:", auth.subject);
|
||||
// }
|
||||
// return await ctx.db.query("test2").collect();
|
||||
// },
|
||||
// });
|
||||
|
||||
10
convex/_generated/api.d.ts
vendored
10
convex/_generated/api.d.ts
vendored
@@ -8,11 +8,8 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type * as abcv from "../abcv.js";
|
||||
import type * as actions_jwt from "../actions/jwt.js";
|
||||
import type * as actions_redis from "../actions/redis.js";
|
||||
import type * as http from "../http.js";
|
||||
import type * as xiong from "../xiong.js";
|
||||
|
||||
import type {
|
||||
ApiFromModules,
|
||||
@@ -21,11 +18,8 @@ import type {
|
||||
} from "convex/server";
|
||||
|
||||
declare const fullApi: ApiFromModules<{
|
||||
abcv: typeof abcv;
|
||||
"actions/jwt": typeof actions_jwt;
|
||||
"actions/redis": typeof actions_redis;
|
||||
http: typeof http;
|
||||
xiong: typeof xiong;
|
||||
}>;
|
||||
|
||||
/**
|
||||
@@ -54,4 +48,6 @@ export declare const internal: FilterApi<
|
||||
FunctionReference<any, "internal">
|
||||
>;
|
||||
|
||||
export declare const components: {};
|
||||
export declare const components: {
|
||||
component: {};
|
||||
};
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { query, mutation, action } from "./_generated/server";
|
||||
import { Kevisual } from '@kevisual/ai/browser'
|
||||
import { v } from "convex/values";
|
||||
export const get = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
const auth = await ctx.auth.getUserIdentity();
|
||||
console.log("Query abcv.get called, auth:", auth);
|
||||
if (auth) {
|
||||
console.log("Authenticated user ID:", auth.subject);
|
||||
}
|
||||
return await ctx.db.query("abcv").collect();
|
||||
},
|
||||
});
|
||||
// import { query, mutation, action } from "./_generated/server";
|
||||
// import { Kevisual } from '@kevisual/ai/browser'
|
||||
// import { v } from "convex/values";
|
||||
// export const get = query({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// const auth = await ctx.auth.getUserIdentity();
|
||||
// console.log("Query abcv.get called, auth:", auth);
|
||||
// if (auth) {
|
||||
// console.log("Authenticated user ID:", auth.subject);
|
||||
// }
|
||||
// return await ctx.db.query("abcv").collect();
|
||||
// },
|
||||
// });
|
||||
|
||||
export const chat = action({
|
||||
args: { message: v.string() },
|
||||
handler: async (ctx, { message }) => {
|
||||
const kevisual = new Kevisual({
|
||||
apiKey: process.env.KEVISUAL_NEW_API_KEY || "",
|
||||
});
|
||||
// export const chat = action({
|
||||
// args: { message: v.string() },
|
||||
// handler: async (ctx, { message }) => {
|
||||
// const kevisual = new Kevisual({
|
||||
// apiKey: process.env.KEVISUAL_NEW_API_KEY || "",
|
||||
// });
|
||||
|
||||
const response = await kevisual.chat({
|
||||
messages: [
|
||||
{ role: "user", content: message }
|
||||
]
|
||||
})
|
||||
return kevisual.responseText;
|
||||
},
|
||||
});
|
||||
// const response = await kevisual.chat({
|
||||
// messages: [
|
||||
// { role: "user", content: message }
|
||||
// ]
|
||||
// })
|
||||
// return kevisual.responseText;
|
||||
// },
|
||||
// });
|
||||
@@ -1,22 +1,22 @@
|
||||
'use node';
|
||||
// 'use node';
|
||||
|
||||
import { query, mutation, action } from "../_generated/server";
|
||||
import { Kevisual } from '@kevisual/ai/browser'
|
||||
import { v } from "convex/values";
|
||||
import { Redis } from "ioredis";
|
||||
const redisClient = new Redis({
|
||||
host: process.env.REDIS_HOST,
|
||||
password: process.env.REDIS_PASSWORD,
|
||||
});
|
||||
let time: any = null;
|
||||
export const isConnected = action({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
const result = await redisClient.ping();
|
||||
if (time === null) {
|
||||
time = new Date();
|
||||
}
|
||||
console.log("Redis PING at", new Date().toISOString(), "since", time);
|
||||
return result === "PONG";
|
||||
},
|
||||
});
|
||||
// import { query, mutation, action } from "../_generated/server";
|
||||
// import { Kevisual } from '@kevisual/ai/browser'
|
||||
// import { v } from "convex/values";
|
||||
// import { Redis } from "ioredis";
|
||||
// const redisClient = new Redis({
|
||||
// host: process.env.REDIS_HOST,
|
||||
// password: process.env.REDIS_PASSWORD,
|
||||
// });
|
||||
// let time: any = null;
|
||||
// export const isConnected = action({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// const result = await redisClient.ping();
|
||||
// if (time === null) {
|
||||
// time = new Date();
|
||||
// }
|
||||
// console.log("Redis PING at", new Date().toISOString(), "since", time);
|
||||
// return result === "PONG";
|
||||
// },
|
||||
// });
|
||||
8
convex/convex.config.ts
Normal file
8
convex/convex.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { defineApp } from "convex/server";
|
||||
import myComponent from "../component/convex.config.ts";
|
||||
|
||||
const app = defineApp();
|
||||
|
||||
// app.use(myComponent);
|
||||
|
||||
export default app;
|
||||
@@ -3,23 +3,23 @@ import { v } from "convex/values";
|
||||
import { authTables } from "@convex-dev/auth/server";
|
||||
// Define a messages table with an index.
|
||||
export default defineSchema({
|
||||
abcv: defineTable({
|
||||
title: v.string(),
|
||||
}),
|
||||
xiong: defineTable({
|
||||
name: v.string(),
|
||||
title: v.string(),
|
||||
}),
|
||||
users: defineTable({
|
||||
id: v.string(), // 外部系统的用户 ID
|
||||
name: v.string(),
|
||||
createdAt: v.string(),
|
||||
lastLoginAt: v.optional(v.string()),
|
||||
}).index("id", ["id"]),
|
||||
sessions: defineTable({
|
||||
userId: v.id("users"),
|
||||
createdAt: v.string(),
|
||||
expiresAt: v.optional(v.string()),
|
||||
token: v.optional(v.string()),
|
||||
}).index("token", ["token"]),
|
||||
// abcv: defineTable({
|
||||
// title: v.string(),
|
||||
// }),
|
||||
// xiong: defineTable({
|
||||
// name: v.string(),
|
||||
// title: v.string(),
|
||||
// }),
|
||||
// users: defineTable({
|
||||
// id: v.string(), // 外部系统的用户 ID
|
||||
// name: v.string(),
|
||||
// createdAt: v.string(),
|
||||
// lastLoginAt: v.optional(v.string()),
|
||||
// }).index("id", ["id"]),
|
||||
// sessions: defineTable({
|
||||
// userId: v.id("users"),
|
||||
// createdAt: v.string(),
|
||||
// expiresAt: v.optional(v.string()),
|
||||
// token: v.optional(v.string()),
|
||||
// }).index("token", ["token"]),
|
||||
});
|
||||
9
convex/wrapper.ts
Normal file
9
convex/wrapper.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// import { query } from "./_generated/server";
|
||||
// import { components } from "./_generated/api";
|
||||
|
||||
// export const getTest2 = query({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// return await ctx.runQuery(components.component.test2.get);
|
||||
// },
|
||||
// });
|
||||
@@ -1,8 +1,8 @@
|
||||
import { query, mutation, action } from "./_generated/server";
|
||||
// import { query, mutation, action } from "./_generated/server";
|
||||
|
||||
export const get = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
return await ctx.db.query("xiong").collect();
|
||||
},
|
||||
});
|
||||
// export const get = query({
|
||||
// args: {},
|
||||
// handler: async (ctx) => {
|
||||
// return await ctx.db.query("xiong").collect();
|
||||
// },
|
||||
// });
|
||||
70
index.ts
70
index.ts
@@ -1,72 +1,10 @@
|
||||
import { ConvexClient, AuthTokenFetcher } from "convex/browser";
|
||||
import { ConvexClient } from "convex/browser";
|
||||
import { api } from "./convex/_generated/api.js";
|
||||
import * as jose from "jose";
|
||||
|
||||
const url = process.env["CONVEX_URL"]
|
||||
const client = new ConvexClient(url!);
|
||||
|
||||
// 加载测试私钥
|
||||
const keys = JSON.parse(await Bun.file("./jwt/privateKey.json").text());
|
||||
const privateKey = await jose.importJWK(keys, "RS256");
|
||||
// 使用主应用的公共 API
|
||||
const test2List = await client.query(api.wrapper.getTest2, {});
|
||||
|
||||
// 生成 RS256 JWT
|
||||
const payload = {
|
||||
iss: "https://convex.kevisual.cn",
|
||||
sub: "user:8fa2be73c2229e85",
|
||||
aud: "convex-app",
|
||||
exp: Math.floor(Date.now() / 1000) + 3600,
|
||||
name: "Test User AA",
|
||||
email: "test@example.com",
|
||||
};
|
||||
const token = await new jose.SignJWT(payload)
|
||||
.setProtectedHeader({
|
||||
"alg": "RS256",
|
||||
"typ": "JWT",
|
||||
"kid": "kid-key-1"
|
||||
})
|
||||
.setIssuedAt()
|
||||
.sign(privateKey);
|
||||
|
||||
console.log("Generated RS256 token:", token);
|
||||
|
||||
const authTokenFetcher: AuthTokenFetcher = async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
|
||||
console.log("AuthTokenFetcher called, forceRefreshToken:", forceRefreshToken);
|
||||
return token;
|
||||
}
|
||||
client.setAuth(authTokenFetcher, (isAuthenticated) => {
|
||||
console.log("Auth isAuthenticated:", isAuthenticated);
|
||||
});
|
||||
// console.log("Auth set up", auth);
|
||||
await Bun.sleep(1000);
|
||||
// const auth = client.getAuth();
|
||||
// console.log("Client auth", auth);
|
||||
const unsubscribe = client.onUpdate(api.abcv.get, {}, async (tasks) => {
|
||||
console.log(tasks);
|
||||
});
|
||||
|
||||
const list = await client.query(api.abcv.get, {});
|
||||
console.log("Initial list:", list);
|
||||
|
||||
// for (let i = 0; i < list.length; i++) {
|
||||
// const a = list[i];
|
||||
// console.log(`Item ${i}:`, a.title);
|
||||
// }
|
||||
// const list = await client.action(api.abcv.chat, { message: "Hello, 1+1=?" });
|
||||
// console.log("Chat response:", list);
|
||||
const xiongList = await client.query(api.xiong.get, {});
|
||||
console.log("Xiong list:", xiongList);
|
||||
// const redisIsConnected = await client.action(api.actions.redis.isConnected, {});
|
||||
// console.log("Redis isConnected:", redisIsConnected);
|
||||
// const sign = await api.auth.signIn({ provider: "convex" })
|
||||
// const sign = await httpClient.action("/auth", { method: "POST" });
|
||||
// console.log("Sign in result:", sign);
|
||||
|
||||
const res = await fetch("http://convex.kevisual.cn:3211/auth", {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
console.log("Custom endpoint response:", data);
|
||||
await Bun.sleep(1000);
|
||||
unsubscribe();
|
||||
await client.close();
|
||||
console.log("Test2 List:", test2List);
|
||||
@@ -4,7 +4,8 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "bunx convex dev"
|
||||
"dev": "bunx convex dev",
|
||||
"convex": "bunx convex dev"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||
@@ -26,4 +27,4 @@
|
||||
"convex": "^1.31.6",
|
||||
"jose": "^6.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/test1.ts
Normal file
72
src/test1.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { ConvexClient, AuthTokenFetcher } from "convex/browser";
|
||||
import { api } from "../convex/_generated/api.js";
|
||||
import * as jose from "jose";
|
||||
|
||||
const url = process.env["CONVEX_URL"]
|
||||
const client = new ConvexClient(url!);
|
||||
|
||||
// 加载测试私钥
|
||||
const keys = JSON.parse(await Bun.file("./jwt/privateKey.json").text());
|
||||
const privateKey = await jose.importJWK(keys, "RS256");
|
||||
|
||||
// 生成 RS256 JWT
|
||||
const payload = {
|
||||
iss: "https://convex.kevisual.cn",
|
||||
sub: "user:8fa2be73c2229e85",
|
||||
aud: "convex-app",
|
||||
exp: Math.floor(Date.now() / 1000) + 3600,
|
||||
name: "Test User AA",
|
||||
email: "test@example.com",
|
||||
};
|
||||
const token = await new jose.SignJWT(payload)
|
||||
.setProtectedHeader({
|
||||
"alg": "RS256",
|
||||
"typ": "JWT",
|
||||
"kid": "kid-key-1"
|
||||
})
|
||||
.setIssuedAt()
|
||||
.sign(privateKey);
|
||||
|
||||
console.log("Generated RS256 token:", token);
|
||||
|
||||
const authTokenFetcher: AuthTokenFetcher = async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
|
||||
console.log("AuthTokenFetcher called, forceRefreshToken:", forceRefreshToken);
|
||||
return token;
|
||||
}
|
||||
client.setAuth(authTokenFetcher, (isAuthenticated) => {
|
||||
console.log("Auth isAuthenticated:", isAuthenticated);
|
||||
});
|
||||
// console.log("Auth set up", auth);
|
||||
await Bun.sleep(1000);
|
||||
// const auth = client.getAuth();
|
||||
// console.log("Client auth", auth);
|
||||
const unsubscribe = client.onUpdate(api.abcv.get, {}, async (tasks) => {
|
||||
console.log(tasks);
|
||||
});
|
||||
|
||||
const list = await client.query(api.abcv.get, {});
|
||||
console.log("Initial list:", list);
|
||||
|
||||
// for (let i = 0; i < list.length; i++) {
|
||||
// const a = list[i];
|
||||
// console.log(`Item ${i}:`, a.title);
|
||||
// }
|
||||
// const list = await client.action(api.abcv.chat, { message: "Hello, 1+1=?" });
|
||||
// console.log("Chat response:", list);
|
||||
const xiongList = await client.query(api.xiong.get, {});
|
||||
console.log("Xiong list:", xiongList);
|
||||
// const redisIsConnected = await client.action(api.actions.redis.isConnected, {});
|
||||
// console.log("Redis isConnected:", redisIsConnected);
|
||||
// const sign = await api.auth.signIn({ provider: "convex" })
|
||||
// const sign = await httpClient.action("/auth", { method: "POST" });
|
||||
// console.log("Sign in result:", sign);
|
||||
|
||||
const res = await fetch("http://convex.kevisual.cn:3211/auth", {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
console.log("Custom endpoint response:", data);
|
||||
await Bun.sleep(1000);
|
||||
unsubscribe();
|
||||
await client.close();
|
||||
Reference in New Issue
Block a user