kitcn 0.0.1 → 0.12.1

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 (93) hide show
  1. package/bin/intent.js +3 -0
  2. package/dist/aggregate/index.d.ts +388 -0
  3. package/dist/aggregate/index.js +37 -0
  4. package/dist/api-entry-BckXqaLb.js +66 -0
  5. package/dist/auth/client/index.d.ts +37 -0
  6. package/dist/auth/client/index.js +217 -0
  7. package/dist/auth/config/index.d.ts +45 -0
  8. package/dist/auth/config/index.js +24 -0
  9. package/dist/auth/generated/index.d.ts +2 -0
  10. package/dist/auth/generated/index.js +3 -0
  11. package/dist/auth/http/index.d.ts +64 -0
  12. package/dist/auth/http/index.js +461 -0
  13. package/dist/auth/index.d.ts +221 -0
  14. package/dist/auth/index.js +1398 -0
  15. package/dist/auth/nextjs/index.d.ts +50 -0
  16. package/dist/auth/nextjs/index.js +81 -0
  17. package/dist/auth-store-Cljlmdmi.js +197 -0
  18. package/dist/builder-CBdG5W6A.js +1974 -0
  19. package/dist/caller-factory-cTXNvYdz.js +216 -0
  20. package/dist/cli.mjs +13264 -0
  21. package/dist/codegen-lF80HSWu.mjs +3416 -0
  22. package/dist/context-utils-HPC5nXzx.d.ts +17 -0
  23. package/dist/create-schema-odyF4kCy.js +156 -0
  24. package/dist/create-schema-orm-DOyiNDCx.js +246 -0
  25. package/dist/crpc/index.d.ts +105 -0
  26. package/dist/crpc/index.js +169 -0
  27. package/dist/customFunctions-C0voKmtx.js +144 -0
  28. package/dist/error-BZEnI7Sq.js +41 -0
  29. package/dist/generated-contract-disabled-Cih4eITO.js +50 -0
  30. package/dist/generated-contract-disabled-D-sOFy92.d.ts +354 -0
  31. package/dist/http-types-DqJubRPJ.d.ts +292 -0
  32. package/dist/meta-utils-0Pu0Nrap.js +117 -0
  33. package/dist/middleware-BUybuv9n.d.ts +34 -0
  34. package/dist/middleware-C2qTZ3V7.js +84 -0
  35. package/dist/orm/index.d.ts +17 -0
  36. package/dist/orm/index.js +10713 -0
  37. package/dist/plugins/index.d.ts +2 -0
  38. package/dist/plugins/index.js +3 -0
  39. package/dist/procedure-caller-DtxLmGwA.d.ts +1467 -0
  40. package/dist/procedure-caller-MWcxhQDv.js +349 -0
  41. package/dist/query-context-B8o6-8kC.js +1518 -0
  42. package/dist/query-context-CFZqIvD7.d.ts +42 -0
  43. package/dist/query-options-Dw7cOyXl.js +121 -0
  44. package/dist/ratelimit/index.d.ts +269 -0
  45. package/dist/ratelimit/index.js +856 -0
  46. package/dist/ratelimit/react/index.d.ts +76 -0
  47. package/dist/ratelimit/react/index.js +183 -0
  48. package/dist/react/index.d.ts +1284 -0
  49. package/dist/react/index.js +2526 -0
  50. package/dist/rsc/index.d.ts +276 -0
  51. package/dist/rsc/index.js +233 -0
  52. package/dist/runtime-CtvJPkur.js +2453 -0
  53. package/dist/server/index.d.ts +5 -0
  54. package/dist/server/index.js +6 -0
  55. package/dist/solid/index.d.ts +1221 -0
  56. package/dist/solid/index.js +2940 -0
  57. package/dist/transformer-DtDhR3Lc.js +194 -0
  58. package/dist/types-BTb_4BaU.d.ts +42 -0
  59. package/dist/types-BiJE7qxR.d.ts +4 -0
  60. package/dist/types-DEJpkIhw.d.ts +88 -0
  61. package/dist/types-HhO_R6pd.d.ts +213 -0
  62. package/dist/validators-B7oIJCAp.js +279 -0
  63. package/dist/validators-vzRKjBJC.d.ts +88 -0
  64. package/dist/watcher.mjs +96 -0
  65. package/dist/where-clause-compiler-DdjN63Io.d.ts +4756 -0
  66. package/package.json +107 -34
  67. package/skills/convex/SKILL.md +486 -0
  68. package/skills/convex/references/features/aggregates.md +353 -0
  69. package/skills/convex/references/features/auth-admin.md +446 -0
  70. package/skills/convex/references/features/auth-organizations.md +1141 -0
  71. package/skills/convex/references/features/auth-polar.md +579 -0
  72. package/skills/convex/references/features/auth.md +470 -0
  73. package/skills/convex/references/features/create-plugins.md +153 -0
  74. package/skills/convex/references/features/http.md +676 -0
  75. package/skills/convex/references/features/migrations.md +162 -0
  76. package/skills/convex/references/features/orm.md +1166 -0
  77. package/skills/convex/references/features/react.md +657 -0
  78. package/skills/convex/references/features/scheduling.md +267 -0
  79. package/skills/convex/references/features/testing.md +209 -0
  80. package/skills/convex/references/setup/auth.md +501 -0
  81. package/skills/convex/references/setup/biome.md +190 -0
  82. package/skills/convex/references/setup/doc-guidelines.md +145 -0
  83. package/skills/convex/references/setup/index.md +761 -0
  84. package/skills/convex/references/setup/next.md +116 -0
  85. package/skills/convex/references/setup/react.md +175 -0
  86. package/skills/convex/references/setup/server.md +473 -0
  87. package/skills/convex/references/setup/start.md +67 -0
  88. package/LICENSE +0 -21
  89. package/README.md +0 -0
  90. package/dist/index.d.mts +0 -5
  91. package/dist/index.d.mts.map +0 -1
  92. package/dist/index.mjs +0 -6
  93. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,217 @@
1
+ 'use client';
2
+ import { C as defaultIsUnauthorized, S as CRPCClientError, d as isSessionSyncGraceActive, g as useAuthValue, h as useAuthStore, n as AuthProvider, o as FetchAccessTokenContext, u as decodeJwtExp } from "../../auth-store-Cljlmdmi.js";
3
+ import { convexClient } from "@convex-dev/better-auth/client/plugins";
4
+ import { ConvexProviderWithAuth, useConvexAuth } from "convex/react";
5
+ import { useCallback, useEffect, useMemo, useRef } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+
8
+ //#region src/auth-client/convex-auth-provider.tsx
9
+ const defaultMutationHandler = () => {
10
+ throw new CRPCClientError({
11
+ code: "UNAUTHORIZED",
12
+ functionName: "mutation"
13
+ });
14
+ };
15
+ const hasActiveSessionData = (session) => {
16
+ if (!session || typeof session !== "object") return false;
17
+ return Boolean(session.session);
18
+ };
19
+ /**
20
+ * Unified auth provider for Convex + Better Auth.
21
+ * Handles token sync, HMR persistence, and auth callbacks.
22
+ *
23
+ * Structure: AuthProvider wraps ConvexAuthProviderInner so that
24
+ * useAuthStore() is available when creating fetchAccessToken.
25
+ */
26
+ function ConvexAuthProvider({ children, client, authClient, initialToken, onMutationUnauthorized, onQueryUnauthorized, isUnauthorized }) {
27
+ useOTTHandler(authClient);
28
+ return /* @__PURE__ */ jsx(AuthProvider, {
29
+ initialValues: useMemo(() => ({
30
+ expiresAt: initialToken ? decodeJwtExp(initialToken) : null,
31
+ token: initialToken ?? null
32
+ }), [initialToken]),
33
+ isUnauthorized: isUnauthorized ?? defaultIsUnauthorized,
34
+ onMutationUnauthorized: onMutationUnauthorized ?? defaultMutationHandler,
35
+ onQueryUnauthorized: onQueryUnauthorized ?? (() => {}),
36
+ children: /* @__PURE__ */ jsx(ConvexAuthProviderInner, {
37
+ authClient,
38
+ client,
39
+ children
40
+ })
41
+ });
42
+ }
43
+ /**
44
+ * Inner provider that has access to AuthStore via useAuthStore().
45
+ * Creates fetchAccessToken and passes it through context (no race condition).
46
+ */
47
+ function ConvexAuthProviderInner({ children, client, authClient }) {
48
+ const authStore = useAuthStore();
49
+ const { data: session, isPending } = authClient.useSession();
50
+ const sessionRef = useRef(session);
51
+ const isPendingRef = useRef(isPending);
52
+ const pendingTokenRef = useRef(null);
53
+ sessionRef.current = session;
54
+ isPendingRef.current = isPending;
55
+ useEffect(() => {
56
+ if (hasActiveSessionData(session)) {
57
+ authStore.set("sessionSyncGraceUntil", null);
58
+ return;
59
+ }
60
+ if (!isPending && !isSessionSyncGraceActive(authStore.get("sessionSyncGraceUntil"))) {
61
+ authStore.set("token", null);
62
+ authStore.set("expiresAt", null);
63
+ authStore.set("isAuthenticated", false);
64
+ authStore.set("sessionSyncGraceUntil", null);
65
+ }
66
+ }, [
67
+ session,
68
+ isPending,
69
+ authStore
70
+ ]);
71
+ const fetchAccessToken = useCallback(async ({ forceRefreshToken = false } = {}) => {
72
+ const fetchFreshToken = () => {
73
+ if (pendingTokenRef.current) return pendingTokenRef.current;
74
+ const cachedToken = authStore.get("token");
75
+ const fetchOptions = { throw: false };
76
+ if (cachedToken && decodeJwtExp(cachedToken) === null) {
77
+ fetchOptions.credentials = "omit";
78
+ fetchOptions.headers = { Authorization: `Bearer ${cachedToken}` };
79
+ }
80
+ pendingTokenRef.current = authClient.convex.token({ fetchOptions }).then((result) => {
81
+ const jwt = result.data?.token || null;
82
+ if (jwt) {
83
+ const exp = decodeJwtExp(jwt);
84
+ authStore.set("token", jwt);
85
+ authStore.set("expiresAt", exp);
86
+ authStore.set("sessionSyncGraceUntil", null);
87
+ return jwt;
88
+ }
89
+ authStore.set("token", null);
90
+ authStore.set("expiresAt", null);
91
+ authStore.set("sessionSyncGraceUntil", null);
92
+ return null;
93
+ }).catch((error) => {
94
+ authStore.set("token", null);
95
+ authStore.set("expiresAt", null);
96
+ authStore.set("sessionSyncGraceUntil", null);
97
+ console.error("[fetchAccessToken] error", error);
98
+ return null;
99
+ }).finally(() => {
100
+ pendingTokenRef.current = null;
101
+ });
102
+ return pendingTokenRef.current;
103
+ };
104
+ const fetchFreshTokenForced = async () => {
105
+ if (pendingTokenRef.current) {
106
+ const token = await pendingTokenRef.current;
107
+ if (token) return token;
108
+ }
109
+ return fetchFreshToken();
110
+ };
111
+ const currentSession = sessionRef.current;
112
+ const currentIsPending = isPendingRef.current;
113
+ const hasSession = hasActiveSessionData(currentSession);
114
+ const hasSessionSyncGrace = isSessionSyncGraceActive(authStore.get("sessionSyncGraceUntil"));
115
+ if (!hasSession) {
116
+ if (currentIsPending || hasSessionSyncGrace) {
117
+ const cachedToken = authStore.get("token");
118
+ if (!forceRefreshToken) {
119
+ if (cachedToken && decodeJwtExp(cachedToken) !== null) return cachedToken;
120
+ return fetchFreshToken();
121
+ }
122
+ const freshToken = await fetchFreshTokenForced();
123
+ if (!freshToken && cachedToken && decodeJwtExp(cachedToken) !== null) {
124
+ authStore.set("token", cachedToken);
125
+ authStore.set("expiresAt", decodeJwtExp(cachedToken));
126
+ return cachedToken;
127
+ }
128
+ return freshToken;
129
+ }
130
+ authStore.set("token", null);
131
+ authStore.set("expiresAt", null);
132
+ authStore.set("sessionSyncGraceUntil", null);
133
+ return null;
134
+ }
135
+ const cachedToken = authStore.get("token");
136
+ const expiresAt = authStore.get("expiresAt");
137
+ const timeRemaining = expiresAt ? expiresAt - Date.now() : 0;
138
+ if (!forceRefreshToken && cachedToken && expiresAt && timeRemaining >= 6e4) return cachedToken;
139
+ if (!forceRefreshToken && pendingTokenRef.current) return pendingTokenRef.current;
140
+ if (forceRefreshToken) return fetchFreshTokenForced();
141
+ return fetchFreshToken();
142
+ }, [authStore, authClient]);
143
+ const useAuth = useCallback(function useConvexAuthHook() {
144
+ const token = authStore.get("token");
145
+ const hasSession = hasActiveSessionData(sessionRef.current);
146
+ const sessionMissing = !hasSession && !isPendingRef.current;
147
+ return {
148
+ isLoading: isPendingRef.current && !token,
149
+ isAuthenticated: sessionMissing ? false : hasSession || token !== null,
150
+ fetchAccessToken
151
+ };
152
+ }, [fetchAccessToken, authStore]);
153
+ return /* @__PURE__ */ jsx(FetchAccessTokenContext.Provider, {
154
+ value: fetchAccessToken,
155
+ children: /* @__PURE__ */ jsx(ConvexProviderWithAuth, {
156
+ client,
157
+ useAuth,
158
+ children: /* @__PURE__ */ jsx(AuthStateSync, { children })
159
+ })
160
+ });
161
+ }
162
+ /**
163
+ * Syncs auth state from useConvexAuth() to the auth store.
164
+ * MUST be inside ConvexProviderWithAuth to access useConvexAuth().
165
+ *
166
+ * Defensive isLoading computation handles SSR hydration race:
167
+ * 1. SSR sets token from cookie
168
+ * 2. Client hydrates
169
+ * 3. Better Auth's useSession() briefly returns null before loading cookie
170
+ * 4. Convex sets isConvexAuthenticated = false (no auth to wait for)
171
+ * 5. Without defensive check, we'd sync { isLoading: false, isAuthenticated: false }
172
+ * 6. Queries would throw UNAUTHORIZED before token is validated
173
+ */
174
+ function AuthStateSync({ children }) {
175
+ const { isLoading: convexIsLoading, isAuthenticated } = useConvexAuth();
176
+ const authStore = useAuthStore();
177
+ const token = useAuthValue("token");
178
+ useEffect(() => {
179
+ const isLoading = convexIsLoading || !!token && !isAuthenticated;
180
+ authStore.set("isLoading", isLoading);
181
+ authStore.set("isAuthenticated", isAuthenticated);
182
+ }, [
183
+ convexIsLoading,
184
+ isAuthenticated,
185
+ token,
186
+ authStore
187
+ ]);
188
+ return children;
189
+ }
190
+ /**
191
+ * Handles cross-domain one-time token (OTT) verification.
192
+ */
193
+ function useOTTHandler(authClient) {
194
+ useEffect(() => {
195
+ (async () => {
196
+ if (typeof window === "undefined" || !window.location?.href) return;
197
+ const url = new URL(window.location.href);
198
+ const token = url.searchParams.get("ott");
199
+ if (token) {
200
+ const authClientWithCrossDomain = authClient;
201
+ url.searchParams.delete("ott");
202
+ window.history.replaceState({}, "", url);
203
+ const session = (await authClientWithCrossDomain.crossDomain.oneTimeToken.verify({ token })).data?.session;
204
+ if (session) {
205
+ await authClient.getSession({ fetchOptions: {
206
+ credentials: "omit",
207
+ headers: { Authorization: `Bearer ${session.token}` }
208
+ } });
209
+ authClientWithCrossDomain.updateSession();
210
+ }
211
+ }
212
+ })();
213
+ }, [authClient]);
214
+ }
215
+
216
+ //#endregion
217
+ export { ConvexAuthProvider, convexClient };
@@ -0,0 +1,45 @@
1
+ import { JwtOptions } from "better-auth/plugins";
2
+
3
+ //#region src/auth/auth-config.d.ts
4
+ type JwksDoc = {
5
+ id: string;
6
+ publicKey: string;
7
+ privateKey: string;
8
+ createdAt: number;
9
+ expiresAt?: number;
10
+ alg?: string;
11
+ crv?: string;
12
+ };
13
+ declare const createPublicJwks: (jwks: JwksDoc[], options?: JwtOptions) => {
14
+ keys: any[];
15
+ };
16
+ declare const getAuthConfigProvider: (opts?: {
17
+ basePath?: string;
18
+ /**
19
+ * @param jwks - Optional static JWKS to avoid fetching from the database.
20
+ *
21
+ * This should be a stringified document from the Better Auth JWKS table. You
22
+ * can create one in the console.
23
+ *
24
+ * Example:
25
+ * ```bash
26
+ * npx convex run generated/auth:generateJwk | npx convex env set JWKS
27
+ * ```
28
+ *
29
+ * Then use it in your auth config:
30
+ * ```ts
31
+ * export default {
32
+ * providers: [getAuthConfigProvider({ jwks: process.env.JWKS })],
33
+ * } satisfies AuthConfig;
34
+ * ```
35
+ */
36
+ jwks?: string;
37
+ }) => {
38
+ type: "customJwt";
39
+ issuer: string;
40
+ applicationID: string;
41
+ algorithm: "RS256";
42
+ jwks: string;
43
+ };
44
+ //#endregion
45
+ export { createPublicJwks, getAuthConfigProvider };
@@ -0,0 +1,24 @@
1
+ //#region src/auth/auth-config.ts
2
+ const createPublicJwks = (jwks, options) => {
3
+ const keyPairConfig = options?.jwks?.keyPairConfig;
4
+ const defaultCrv = keyPairConfig && "crv" in keyPairConfig ? keyPairConfig.crv : void 0;
5
+ return { keys: jwks.map((keySet) => ({
6
+ alg: keySet.alg ?? options?.jwks?.keyPairConfig?.alg ?? "EdDSA",
7
+ crv: keySet.crv ?? defaultCrv,
8
+ ...JSON.parse(keySet.publicKey),
9
+ kid: keySet.id
10
+ })) };
11
+ };
12
+ const getAuthConfigProvider = (opts) => {
13
+ const parsedJwks = opts?.jwks ? JSON.parse(opts.jwks) : void 0;
14
+ return {
15
+ type: "customJwt",
16
+ issuer: `${process.env.CONVEX_SITE_URL}`,
17
+ applicationID: "convex",
18
+ algorithm: "RS256",
19
+ jwks: parsedJwks ? `data:text/plain;charset=utf-8;base64,${btoa(JSON.stringify(createPublicJwks(parsedJwks)))}` : `${process.env.CONVEX_SITE_URL}${opts?.basePath ?? "/api/auth"}/convex/jwks`
20
+ };
21
+ };
22
+
23
+ //#endregion
24
+ export { createPublicJwks, getAuthConfigProvider };
@@ -0,0 +1,2 @@
1
+ import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-D-sOFy92.js";
2
+ export { type AuthRuntime, BetterAuthOptionsWithoutDatabase, type GeneratedAuthDisabledReasonKind, GenericAuthBeforeResult, GenericAuthDefinition, GenericAuthTriggerChange, GenericAuthTriggerHandlers, GenericAuthTriggers, createDisabledAuthRuntime, defineAuth, getGeneratedAuthDisabledReason };
@@ -0,0 +1,3 @@
1
+ import { i as defineAuth, n as createDisabledAuthRuntime, r as getGeneratedAuthDisabledReason } from "../../generated-contract-disabled-Cih4eITO.js";
2
+
3
+ export { createDisabledAuthRuntime, defineAuth, getGeneratedAuthDisabledReason };
@@ -0,0 +1,64 @@
1
+ import { t as GetAuth } from "../../types-BiJE7qxR.js";
2
+ import { HttpRouter } from "convex/server";
3
+ import { MiddlewareHandler } from "hono";
4
+
5
+ //#region src/auth/middleware.d.ts
6
+ interface AuthMiddlewareOptions {
7
+ /** Base path for auth routes (default: '/api/auth') */
8
+ basePath?: string;
9
+ /** Log request/response headers for debugging */
10
+ verbose?: boolean;
11
+ }
12
+ /**
13
+ * Create auth middleware that handles auth routes and OpenID well-known redirect.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { Hono } from 'hono';
18
+ * import { cors } from 'hono/cors';
19
+ * import { authMiddleware } from 'kitcn/auth/http';
20
+ * import { createHttpRouter } from 'kitcn/server';
21
+ *
22
+ * const app = new Hono();
23
+ * app.use('/api/*', cors({ origin: process.env.SITE_URL, credentials: true }));
24
+ * app.use(authMiddleware(getAuth));
25
+ *
26
+ * export default createHttpRouter(app, httpRouter);
27
+ * ```
28
+ */
29
+ declare function authMiddleware<Ctx = unknown>(getAuth: GetAuth<Ctx, {
30
+ handler: (request: Request) => Promise<Response>;
31
+ }>, opts?: AuthMiddlewareOptions): MiddlewareHandler;
32
+ //#endregion
33
+ //#region src/auth/registerRoutes.d.ts
34
+ type TrustedOriginsOption = (string | null | undefined)[] | ((request?: Request) => (string | null | undefined)[] | Promise<(string | null | undefined)[]>);
35
+ type AuthRouteContract = {
36
+ $context: Promise<{
37
+ options: {
38
+ trustedOrigins?: TrustedOriginsOption;
39
+ };
40
+ }>;
41
+ handler: (request: Request) => Promise<Response>;
42
+ options: {
43
+ basePath?: string;
44
+ baseURL?: string;
45
+ trustedOrigins?: TrustedOriginsOption;
46
+ };
47
+ };
48
+ declare const registerRoutes: <Ctx>(http: HttpRouter, getAuth: GetAuth<Ctx, AuthRouteContract>, opts?: {
49
+ cors?: {
50
+ allowedHeaders?: string[];
51
+ allowedOrigins?: string[];
52
+ exposedHeaders?: string[];
53
+ } | boolean;
54
+ verbose?: boolean;
55
+ }) => void;
56
+ //#endregion
57
+ //#region src/auth-http/index.d.ts
58
+ /**
59
+ * Install Convex-safe polyfills required by Better Auth's HTTP handling.
60
+ * This runs automatically when importing `kitcn/auth/http`.
61
+ */
62
+ declare function installAuthHttpPolyfills(): void;
63
+ //#endregion
64
+ export { authMiddleware, installAuthHttpPolyfills, registerRoutes };