@lupinum/better-convex-nuxt 0.8.0-beta.40
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/LICENSE +21 -0
- package/LICENSES/Apache-2.0.txt +201 -0
- package/README.md +151 -0
- package/THIRD_PARTY_NOTICES.md +38 -0
- package/dist/module.d.mts +55 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +309 -0
- package/dist/runtime/auth/auth-identity.d.ts +31 -0
- package/dist/runtime/auth/auth-identity.js +21 -0
- package/dist/runtime/auth/better-auth-browser-adapter.d.ts +33 -0
- package/dist/runtime/auth/better-auth-browser-adapter.js +215 -0
- package/dist/runtime/auth/client-engine-types.d.ts +4 -0
- package/dist/runtime/auth/client-engine-types.js +0 -0
- package/dist/runtime/auth/integrated-client.d.ts +25 -0
- package/dist/runtime/auth/integrated-client.js +132 -0
- package/dist/runtime/auth/operation-tracker.d.ts +7 -0
- package/dist/runtime/auth/operation-tracker.js +14 -0
- package/dist/runtime/auth/session-synchronization.d.ts +23 -0
- package/dist/runtime/auth/session-synchronization.js +156 -0
- package/dist/runtime/auth/token-fetcher.d.ts +66 -0
- package/dist/runtime/auth/token-fetcher.js +131 -0
- package/dist/runtime/auth/validate-auth-client-definition.d.ts +12 -0
- package/dist/runtime/auth/validate-auth-client-definition.js +47 -0
- package/dist/runtime/auth-client/convex-client-plugin.d.ts +31 -0
- package/dist/runtime/auth-client/convex-client-plugin.js +14 -0
- package/dist/runtime/auth-client/definition-types.d.ts +6 -0
- package/dist/runtime/auth-client/definition-types.js +0 -0
- package/dist/runtime/auth-client/empty-definition.d.ts +2 -0
- package/dist/runtime/auth-client/empty-definition.js +2 -0
- package/dist/runtime/auth-client/index.d.ts +71 -0
- package/dist/runtime/auth-client/index.js +3 -0
- package/dist/runtime/cli/auth-schema.d.ts +2 -0
- package/dist/runtime/cli/auth-schema.js +169 -0
- package/dist/runtime/cli/convex.d.ts +11 -0
- package/dist/runtime/cli/convex.js +274 -0
- package/dist/runtime/composables/useConvex.d.ts +4 -0
- package/dist/runtime/composables/useConvex.js +9 -0
- package/dist/runtime/composables/useConvexAction.d.ts +4 -0
- package/dist/runtime/composables/useConvexAction.js +18 -0
- package/dist/runtime/composables/useConvexAttachment.d.ts +9 -0
- package/dist/runtime/composables/useConvexAttachment.js +14 -0
- package/dist/runtime/composables/useConvexAuth.d.ts +10 -0
- package/dist/runtime/composables/useConvexAuth.js +37 -0
- package/dist/runtime/composables/useConvexConfig.d.ts +12 -0
- package/dist/runtime/composables/useConvexConfig.js +7 -0
- package/dist/runtime/composables/useConvexConnectionState.d.ts +33 -0
- package/dist/runtime/composables/useConvexConnectionState.js +24 -0
- package/dist/runtime/composables/useConvexFileUpload.d.ts +169 -0
- package/dist/runtime/composables/useConvexFileUpload.js +198 -0
- package/dist/runtime/composables/useConvexMutation.d.ts +13 -0
- package/dist/runtime/composables/useConvexMutation.js +24 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.d.ts +13 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.js +256 -0
- package/dist/runtime/composables/useConvexQuery.d.ts +19 -0
- package/dist/runtime/composables/useConvexQuery.js +308 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.d.ts +33 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.js +308 -0
- package/dist/runtime/convex-auth/adapter/define-functions.d.ts +160 -0
- package/dist/runtime/convex-auth/adapter/define-functions.js +497 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.d.ts +16 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.js +332 -0
- package/dist/runtime/convex-auth/adapter/metadata.d.ts +44 -0
- package/dist/runtime/convex-auth/adapter/metadata.js +91 -0
- package/dist/runtime/convex-auth/adapter/query.d.ts +32 -0
- package/dist/runtime/convex-auth/adapter/query.js +275 -0
- package/dist/runtime/convex-auth/adapter/relationships.d.ts +20 -0
- package/dist/runtime/convex-auth/adapter/relationships.js +128 -0
- package/dist/runtime/convex-auth/component/_generated/api.js +5 -0
- package/dist/runtime/convex-auth/component/_generated/component.d.ts +116 -0
- package/dist/runtime/convex-auth/component/_generated/component.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/dataModel.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/server.js +16 -0
- package/dist/runtime/convex-auth/component/adapter.d.ts +142 -0
- package/dist/runtime/convex-auth/component/adapter.js +16 -0
- package/dist/runtime/convex-auth/component/convex.config.d.ts +2 -0
- package/dist/runtime/convex-auth/component/convex.config.js +3 -0
- package/dist/runtime/convex-auth/component/schema.d.ts +799 -0
- package/dist/runtime/convex-auth/component/schema.js +180 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.d.ts +2094 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.js +2161 -0
- package/dist/runtime/convex-auth/context.d.ts +5 -0
- package/dist/runtime/convex-auth/context.js +8 -0
- package/dist/runtime/convex-auth/create-auth-component.d.ts +41 -0
- package/dist/runtime/convex-auth/create-auth-component.js +157 -0
- package/dist/runtime/convex-auth/index.d.ts +11 -0
- package/dist/runtime/convex-auth/index.js +7 -0
- package/dist/runtime/convex-auth/internal-session.d.ts +2 -0
- package/dist/runtime/convex-auth/internal-session.js +1 -0
- package/dist/runtime/convex-auth/jwks-rotation.d.ts +58 -0
- package/dist/runtime/convex-auth/jwks-rotation.js +163 -0
- package/dist/runtime/convex-auth/oauth-live-access.d.ts +17 -0
- package/dist/runtime/convex-auth/oauth-live-access.js +78 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.d.ts +10 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.js +170 -0
- package/dist/runtime/convex-auth/oauth-resource.d.ts +39 -0
- package/dist/runtime/convex-auth/oauth-resource.js +118 -0
- package/dist/runtime/convex-auth/oauth-security.d.ts +82 -0
- package/dist/runtime/convex-auth/oauth-security.js +454 -0
- package/dist/runtime/convex-auth/origin.d.ts +4 -0
- package/dist/runtime/convex-auth/origin.js +9 -0
- package/dist/runtime/convex-auth/plugin.d.ts +18 -0
- package/dist/runtime/convex-auth/plugin.js +605 -0
- package/dist/runtime/convex-auth/provider.d.ts +2 -0
- package/dist/runtime/convex-auth/provider.js +11 -0
- package/dist/runtime/convex-auth/test.d.ts +410 -0
- package/dist/runtime/convex-auth/test.js +9 -0
- package/dist/runtime/convex-auth/types.d.ts +18 -0
- package/dist/runtime/convex-auth/types.js +0 -0
- package/dist/runtime/convex-auth/user-projection.d.ts +106 -0
- package/dist/runtime/convex-auth/user-projection.js +128 -0
- package/dist/runtime/devtools/auth-proxy-registry.d.ts +4 -0
- package/dist/runtime/devtools/auth-proxy-registry.js +47 -0
- package/dist/runtime/devtools/bridge-setup.d.ts +21 -0
- package/dist/runtime/devtools/bridge-setup.js +165 -0
- package/dist/runtime/devtools/path-utils.d.ts +2 -0
- package/dist/runtime/devtools/path-utils.js +12 -0
- package/dist/runtime/devtools/server.d.ts +2 -0
- package/dist/runtime/devtools/server.js +108 -0
- package/dist/runtime/devtools/setup-client.d.ts +16 -0
- package/dist/runtime/devtools/setup-client.js +43 -0
- package/dist/runtime/devtools/sink.d.ts +18 -0
- package/dist/runtime/devtools/sink.js +110 -0
- package/dist/runtime/devtools/transport.d.ts +16 -0
- package/dist/runtime/devtools/transport.js +149 -0
- package/dist/runtime/devtools/types.d.ts +167 -0
- package/dist/runtime/devtools/types.js +1 -0
- package/dist/runtime/devtools/ui/dist/200.html +1 -0
- package/dist/runtime/devtools/ui/dist/404.html +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/C4MASuCh.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DJHkqtZq.js +3 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DWwrCltl.js +2 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DZ_UiYoH.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/_m9ujb-i.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/latest.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/meta/better-convex-nuxt-devtools.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/entry.DpFDKYZ5.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-404.DYUJo5xt.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-500.DQdoJJXg.css +1 -0
- package/dist/runtime/devtools/ui/dist/convex-logo.svg +5 -0
- package/dist/runtime/devtools/ui/dist/index.html +1 -0
- package/dist/runtime/errors/index.d.ts +7 -0
- package/dist/runtime/errors/index.js +5 -0
- package/dist/runtime/middleware/convex-auth.global.d.ts +2 -0
- package/dist/runtime/middleware/convex-auth.global.js +31 -0
- package/dist/runtime/plugin.auth.client.d.ts +3 -0
- package/dist/runtime/plugin.auth.client.js +217 -0
- package/dist/runtime/plugin.client.d.ts +3 -0
- package/dist/runtime/plugin.client.js +43 -0
- package/dist/runtime/plugin.server.d.ts +12 -0
- package/dist/runtime/plugin.server.js +98 -0
- package/dist/runtime/plugins/convex-call-error-payload.d.ts +14 -0
- package/dist/runtime/plugins/convex-call-error-payload.js +12 -0
- package/dist/runtime/runtime-context.d.ts +26 -0
- package/dist/runtime/runtime-context.js +48 -0
- package/dist/runtime/server/api/auth/[...].d.ts +10 -0
- package/dist/runtime/server/api/auth/[...].js +509 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.d.ts +2 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.js +6 -0
- package/dist/runtime/server/api/auth/body-size.d.ts +15 -0
- package/dist/runtime/server/api/auth/body-size.js +179 -0
- package/dist/runtime/server/api/auth/headers.d.ts +6 -0
- package/dist/runtime/server/api/auth/headers.js +98 -0
- package/dist/runtime/server/api/auth/jwks.d.ts +2 -0
- package/dist/runtime/server/api/auth/jwks.js +6 -0
- package/dist/runtime/server/api/auth/security.d.ts +14 -0
- package/dist/runtime/server/api/auth/security.js +85 -0
- package/dist/runtime/server/api/release-fingerprint.d.ts +2 -0
- package/dist/runtime/server/api/release-fingerprint.js +36 -0
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/runtime-config.d.ts +7 -0
- package/dist/runtime/server/plugins/runtime-config.js +7 -0
- package/dist/runtime/server/utils/auth-snapshot.d.ts +26 -0
- package/dist/runtime/server/utils/auth-snapshot.js +165 -0
- package/dist/runtime/server/utils/http.d.ts +16 -0
- package/dist/runtime/server/utils/http.js +133 -0
- package/dist/runtime/server/utils/server-convex-caller.d.ts +31 -0
- package/dist/runtime/server/utils/server-convex-caller.js +151 -0
- package/dist/runtime/server/utils/server-convex-options.d.ts +83 -0
- package/dist/runtime/server/utils/server-convex-options.js +69 -0
- package/dist/runtime/server/utils/signed-client-ip.d.ts +6 -0
- package/dist/runtime/server/utils/signed-client-ip.js +29 -0
- package/dist/runtime/server/utils/ssr-auth-headers.d.ts +26 -0
- package/dist/runtime/server/utils/ssr-auth-headers.js +49 -0
- package/dist/runtime/server/utils/token-exchange.d.ts +27 -0
- package/dist/runtime/server/utils/token-exchange.js +96 -0
- package/dist/runtime/shared/auth-cookie.d.ts +4 -0
- package/dist/runtime/shared/auth-cookie.js +25 -0
- package/dist/runtime/shared/auth-origin.d.ts +15 -0
- package/dist/runtime/shared/auth-origin.js +42 -0
- package/dist/runtime/shared/bounded-stream.d.ts +2 -0
- package/dist/runtime/shared/bounded-stream.js +50 -0
- package/dist/runtime/shared/client-ip.d.ts +21 -0
- package/dist/runtime/shared/client-ip.js +123 -0
- package/dist/runtime/shared/release-fingerprint.d.ts +5 -0
- package/dist/runtime/shared/release-fingerprint.js +17 -0
- package/dist/runtime/types.d.ts +19 -0
- package/dist/runtime/utils/auth-config.d.ts +24 -0
- package/dist/runtime/utils/auth-config.js +45 -0
- package/dist/runtime/utils/auth-contract.d.ts +22 -0
- package/dist/runtime/utils/auth-contract.js +0 -0
- package/dist/runtime/utils/auth-errors.d.ts +5 -0
- package/dist/runtime/utils/auth-errors.js +22 -0
- package/dist/runtime/utils/auth-identity-state.d.ts +4 -0
- package/dist/runtime/utils/auth-identity-state.js +8 -0
- package/dist/runtime/utils/auth-pending-state.d.ts +13 -0
- package/dist/runtime/utils/auth-pending-state.js +4 -0
- package/dist/runtime/utils/auth-pending.d.ts +10 -0
- package/dist/runtime/utils/auth-pending.js +30 -0
- package/dist/runtime/utils/auth-route-protection.d.ts +16 -0
- package/dist/runtime/utils/auth-route-protection.js +58 -0
- package/dist/runtime/utils/auth-status.d.ts +47 -0
- package/dist/runtime/utils/auth-status.js +8 -0
- package/dist/runtime/utils/bounded-convex-fetch.d.ts +18 -0
- package/dist/runtime/utils/bounded-convex-fetch.js +152 -0
- package/dist/runtime/utils/callable-devtools.d.ts +17 -0
- package/dist/runtime/utils/callable-devtools.js +49 -0
- package/dist/runtime/utils/callable-observer.d.ts +2 -0
- package/dist/runtime/utils/callable-observer.js +1 -0
- package/dist/runtime/utils/composable-scope.d.ts +2 -0
- package/dist/runtime/utils/composable-scope.js +8 -0
- package/dist/runtime/utils/config-defaults.d.ts +8 -0
- package/dist/runtime/utils/config-defaults.js +8 -0
- package/dist/runtime/utils/convex-cache.d.ts +68 -0
- package/dist/runtime/utils/convex-cache.js +47 -0
- package/dist/runtime/utils/convex-config.d.ts +16 -0
- package/dist/runtime/utils/convex-config.js +50 -0
- package/dist/runtime/utils/convex-shared.d.ts +67 -0
- package/dist/runtime/utils/convex-shared.js +134 -0
- package/dist/runtime/utils/identity-changed-error.d.ts +4 -0
- package/dist/runtime/utils/identity-changed-error.js +12 -0
- package/dist/runtime/utils/identity-key.d.ts +19 -0
- package/dist/runtime/utils/identity-key.js +10 -0
- package/dist/runtime/utils/integrated-auth-client.d.ts +5 -0
- package/dist/runtime/utils/integrated-auth-client.js +0 -0
- package/dist/runtime/utils/logger.d.ts +42 -0
- package/dist/runtime/utils/logger.js +190 -0
- package/dist/runtime/utils/mime-type.d.ts +33 -0
- package/dist/runtime/utils/mime-type.js +10 -0
- package/dist/runtime/utils/query-execution-gate.d.ts +47 -0
- package/dist/runtime/utils/query-execution-gate.js +63 -0
- package/dist/runtime/utils/query-execution.d.ts +8 -0
- package/dist/runtime/utils/query-execution.js +19 -0
- package/dist/runtime/utils/query-foundation.d.ts +20 -0
- package/dist/runtime/utils/query-foundation.js +39 -0
- package/dist/runtime/utils/query-state.d.ts +12 -0
- package/dist/runtime/utils/query-state.js +12 -0
- package/dist/runtime/utils/reactive-args.d.ts +5 -0
- package/dist/runtime/utils/reactive-args.js +42 -0
- package/dist/runtime/utils/runtime-config-normalize.d.ts +22 -0
- package/dist/runtime/utils/runtime-config-normalize.js +28 -0
- package/dist/runtime/utils/runtime-config.d.ts +4 -0
- package/dist/runtime/utils/runtime-config.js +8 -0
- package/dist/runtime/utils/sanitize-diagnostic.d.ts +6 -0
- package/dist/runtime/utils/sanitize-diagnostic.js +81 -0
- package/dist/runtime/utils/shared-helpers.d.ts +46 -0
- package/dist/runtime/utils/shared-helpers.js +139 -0
- package/dist/runtime/utils/site-url.d.ts +4 -0
- package/dist/runtime/utils/site-url.js +15 -0
- package/dist/runtime/utils/ssr-pagination-state.d.ts +3 -0
- package/dist/runtime/utils/ssr-pagination-state.js +3 -0
- package/dist/runtime/utils/types.d.ts +29 -0
- package/dist/runtime/utils/types.js +0 -0
- package/dist/runtime/utils/upload-core.d.ts +16 -0
- package/dist/runtime/utils/upload-core.js +116 -0
- package/dist/types.d.mts +21 -0
- package/package.json +253 -0
- package/security/upstream-convex-better-auth.json +477 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { BetterAuthClientOptions } from 'better-auth/client';
|
|
2
|
+
import type { VueAuthClient } from 'better-auth/vue';
|
|
3
|
+
import type { AuthClientPlugins, ConvexAuthClientDefinitionOptions } from './definition-types.js';
|
|
4
|
+
export type { IntegratedAuthClient } from '../utils/integrated-auth-client.js';
|
|
5
|
+
/** A frozen, framework-free description of the consumer's client (no instance). */
|
|
6
|
+
export interface ConvexAuthClientDefinition<Plugins extends AuthClientPlugins> {
|
|
7
|
+
readonly options: ConvexAuthClientDefinitionOptions<Plugins>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Capture the typed shape of a Convex Better Auth client without instantiating
|
|
11
|
+
* one. The `const` plugins generic preserves the tuple so plugin-method
|
|
12
|
+
* inference survives into `InferRegisteredConvexAuthClient`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // app/convex-auth.ts — import your plugin clients (organizationClient,
|
|
17
|
+
* // apiKeyClient) and defineConvexAuthClient, then:
|
|
18
|
+
* export default defineConvexAuthClient({
|
|
19
|
+
* plugins: [organizationClient(), apiKeyClient()],
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function defineConvexAuthClient<const Plugins extends AuthClientPlugins = []>(options?: ConvexAuthClientDefinitionOptions<Plugins>): ConvexAuthClientDefinition<Plugins>;
|
|
24
|
+
/**
|
|
25
|
+
* Augmentable registry . The module-generated type template (produced
|
|
26
|
+
* by `src/module.ts` via Nuxt Kit `addTypeTemplate`) adds a `definition` member
|
|
27
|
+
* whose type is `typeof` the resolved consumer definition:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* declare module '@lupinum/better-convex-nuxt/auth-client' {
|
|
31
|
+
* interface ConvexAuthClientRegistry {
|
|
32
|
+
* definition: typeof definition
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Augmenting this exact module (where the interface is declared) is required:
|
|
38
|
+
* `InferRegisteredConvexAuthClient` below reads this interface, and a
|
|
39
|
+
* cross-module re-export augmentation would not merge into it. The packed
|
|
40
|
+
* auth-client typing fixture covers this boundary.
|
|
41
|
+
*/
|
|
42
|
+
export interface ConvexAuthClientRegistry {
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Better Auth's `plugins` option is a MUTABLE array; a definition holds a
|
|
46
|
+
* readonly tuple, so strip `readonly` when spreading into resolved options.
|
|
47
|
+
*/
|
|
48
|
+
type MutablePlugins<P extends readonly unknown[]> = {
|
|
49
|
+
-readonly [I in keyof P]: P[I];
|
|
50
|
+
};
|
|
51
|
+
/** Extract the plugins tuple from a registered definition VALUE (never `ReturnType<typeof factory>`). */
|
|
52
|
+
type PluginsOf<D> = D extends ConvexAuthClientDefinition<infer P> ? P : [];
|
|
53
|
+
/**
|
|
54
|
+
* The options actually handed to `createAuthClient`: base options via `Omit`
|
|
55
|
+
* plus the module-owned `baseURL` and the consumer plugin tuple.
|
|
56
|
+
* tuple. The full `BetterAuthClientOptions` is deliberately NOT re-intersected.
|
|
57
|
+
*/
|
|
58
|
+
type ResolvedOptions<Plugins extends AuthClientPlugins> = Omit<BetterAuthClientOptions, 'baseURL' | 'plugins'> & {
|
|
59
|
+
baseURL: string;
|
|
60
|
+
plugins: [...MutablePlugins<Plugins>];
|
|
61
|
+
};
|
|
62
|
+
/** The inferred client type for the library-owned options with no consumer plugins. */
|
|
63
|
+
export type BaseAuthClient = VueAuthClient<ResolvedOptions<[]>>;
|
|
64
|
+
/**
|
|
65
|
+
* The registered raw Better Auth shape used to infer the integrated client.
|
|
66
|
+
* Exposes plugin methods when a definition is registered; falls back to the
|
|
67
|
+
* base Better Auth client type otherwise.
|
|
68
|
+
*/
|
|
69
|
+
export type InferRegisteredConvexAuthClient = ConvexAuthClientRegistry extends {
|
|
70
|
+
definition: infer D;
|
|
71
|
+
} ? VueAuthClient<ResolvedOptions<PluginsOf<D>>> : BaseAuthClient;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { access, mkdir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
5
|
+
import { getAuthTables } from "better-auth/db";
|
|
6
|
+
import { createJiti } from "jiti";
|
|
7
|
+
import { generateAuthSchemaArtifacts } from "../convex-auth/adapter/generate-schema.js";
|
|
8
|
+
const SCHEMA_BASE_URL = "https://schema.invalid";
|
|
9
|
+
const SCHEMA_SECRET = "schema-generation-only-value-never-used-at-runtime";
|
|
10
|
+
const CLEARED_ENVIRONMENT = [
|
|
11
|
+
"SITE_URL",
|
|
12
|
+
"CONVEX_SITE_URL",
|
|
13
|
+
"AUTH_SECRET",
|
|
14
|
+
"BETTER_AUTH_SECRET",
|
|
15
|
+
"BETTER_AUTH_SECRETS",
|
|
16
|
+
"BCN_AUTH_PROXY_IP_SECRET"
|
|
17
|
+
];
|
|
18
|
+
function usage() {
|
|
19
|
+
return [
|
|
20
|
+
"Generate a paired Better Convex Nuxt local auth schema and metadata descriptor.",
|
|
21
|
+
"",
|
|
22
|
+
"Usage:",
|
|
23
|
+
" better-convex-nuxt-auth-schema --config <schema-options.ts> [--output <directory>] [--check]",
|
|
24
|
+
"",
|
|
25
|
+
"The config must default-export environment-independent BetterAuthOptions using:",
|
|
26
|
+
` baseURL: ${SCHEMA_BASE_URL}`,
|
|
27
|
+
` secret: ${SCHEMA_SECRET}`,
|
|
28
|
+
"",
|
|
29
|
+
"The config is loaded as TypeScript and may import local schema plugin modules."
|
|
30
|
+
].join("\n");
|
|
31
|
+
}
|
|
32
|
+
function valueAfter(args, index, flag) {
|
|
33
|
+
const value = args[index + 1];
|
|
34
|
+
if (!value || value.startsWith("--")) throw new Error(`${flag} requires a value.`);
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
function parseArgs(args) {
|
|
38
|
+
const options = { check: false, help: false };
|
|
39
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
40
|
+
const argument = args[index];
|
|
41
|
+
switch (argument) {
|
|
42
|
+
case "--check":
|
|
43
|
+
options.check = true;
|
|
44
|
+
break;
|
|
45
|
+
case "--config":
|
|
46
|
+
if (options.config) throw new Error("--config may be provided only once.");
|
|
47
|
+
options.config = valueAfter(args, index, "--config");
|
|
48
|
+
index += 1;
|
|
49
|
+
break;
|
|
50
|
+
case "--help":
|
|
51
|
+
case "-h":
|
|
52
|
+
options.help = true;
|
|
53
|
+
break;
|
|
54
|
+
case "--output":
|
|
55
|
+
if (options.output) throw new Error("--output may be provided only once.");
|
|
56
|
+
options.output = valueAfter(args, index, "--output");
|
|
57
|
+
index += 1;
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`Unknown argument: ${argument}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return options;
|
|
64
|
+
}
|
|
65
|
+
function isRecord(value) {
|
|
66
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
67
|
+
}
|
|
68
|
+
function requireSchemaOptions(value) {
|
|
69
|
+
if (!isRecord(value)) throw new Error("Schema config must default-export BetterAuthOptions.");
|
|
70
|
+
if (value.baseURL !== SCHEMA_BASE_URL || value.secret !== SCHEMA_SECRET) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
"Schema config must use the reserved environment-independent baseURL and secret."
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
async function readIfPresent(path) {
|
|
78
|
+
try {
|
|
79
|
+
return await readFile(path, "utf8");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (isRecord(error) && error.code === "ENOENT") return void 0;
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function resolveSchemaTarget(configPath, output) {
|
|
86
|
+
const resolvedOutput = output ? resolve(output) : dirname(configPath);
|
|
87
|
+
const target = output && extname(resolvedOutput) ? resolvedOutput : join(resolvedOutput, "schema.ts");
|
|
88
|
+
if (basename(target) !== "schema.ts" || basename(dirname(target)) === "convex") {
|
|
89
|
+
throw new Error("Output must be a local component schema.ts, not the application schema.");
|
|
90
|
+
}
|
|
91
|
+
return target;
|
|
92
|
+
}
|
|
93
|
+
async function writePair(outputs) {
|
|
94
|
+
const temporaryFiles = /* @__PURE__ */ new Map();
|
|
95
|
+
const sequence = `${process.pid}.${Date.now()}`;
|
|
96
|
+
try {
|
|
97
|
+
for (const [target, contents] of outputs) {
|
|
98
|
+
await mkdir(dirname(target), { recursive: true });
|
|
99
|
+
const temporary = join(dirname(target), `.${basename(target)}.${sequence}.tmp`);
|
|
100
|
+
await writeFile(temporary, contents, { encoding: "utf8", flag: "wx", mode: 420 });
|
|
101
|
+
temporaryFiles.set(target, temporary);
|
|
102
|
+
}
|
|
103
|
+
const orderedTargets = [...outputs.keys()].sort(
|
|
104
|
+
(left, right) => left.endsWith("schemaMetadata.ts") ? -1 : right.endsWith("schemaMetadata.ts") ? 1 : 0
|
|
105
|
+
);
|
|
106
|
+
for (const target of orderedTargets) {
|
|
107
|
+
const temporary = temporaryFiles.get(target);
|
|
108
|
+
if (!temporary) throw new Error("Unable to stage generated auth artifacts.");
|
|
109
|
+
await rename(temporary, target);
|
|
110
|
+
temporaryFiles.delete(target);
|
|
111
|
+
}
|
|
112
|
+
} finally {
|
|
113
|
+
await Promise.all([...temporaryFiles.values()].map((path) => rm(path, { force: true })));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function generate(options) {
|
|
117
|
+
if (!options.config) throw new Error("--config is required.");
|
|
118
|
+
const configPath = await realpath(resolve(options.config));
|
|
119
|
+
await access(configPath, constants.R_OK);
|
|
120
|
+
for (const name of CLEARED_ENVIRONMENT) Reflect.deleteProperty(process.env, name);
|
|
121
|
+
let configModule;
|
|
122
|
+
try {
|
|
123
|
+
const jiti = createJiti(import.meta.url, { interopDefault: false });
|
|
124
|
+
configModule = await jiti.import(configPath);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (isRecord(error) && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
127
|
+
throw new Error("Unable to import schema config or one of its dependencies.");
|
|
128
|
+
}
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
const schemaOptions = requireSchemaOptions(configModule.default);
|
|
132
|
+
const artifacts = generateAuthSchemaArtifacts(getAuthTables(schemaOptions));
|
|
133
|
+
const schemaTarget = resolveSchemaTarget(configPath, options.output);
|
|
134
|
+
const outputs = /* @__PURE__ */ new Map([
|
|
135
|
+
[schemaTarget, artifacts.schemaCode],
|
|
136
|
+
[join(dirname(schemaTarget), "schemaMetadata.ts"), artifacts.metadataCode]
|
|
137
|
+
]);
|
|
138
|
+
if (options.check) {
|
|
139
|
+
const stale = [];
|
|
140
|
+
for (const [target, contents] of outputs) {
|
|
141
|
+
if (await readIfPresent(target) !== contents) stale.push(target);
|
|
142
|
+
}
|
|
143
|
+
if (stale.length > 0) {
|
|
144
|
+
for (const target of stale) console.error(`stale: ${target}`);
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
console.log("Auth schema and metadata are current.");
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
await writePair(outputs);
|
|
151
|
+
for (const target of outputs.keys()) console.log(`generated: ${target}`);
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
async function main() {
|
|
155
|
+
const options = parseArgs(process.argv.slice(2));
|
|
156
|
+
if (options.help) {
|
|
157
|
+
console.log(usage());
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
return await generate(options);
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
process.exitCode = await main();
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(
|
|
166
|
+
`[better-convex-nuxt-auth-schema] ${error instanceof Error ? error.message : "failed"}`
|
|
167
|
+
);
|
|
168
|
+
process.exitCode = 1;
|
|
169
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
type ConvexAuthorityKind = 'deployment-key' | 'deployment-name' | 'self-hosted';
|
|
3
|
+
/** Validate that the fixed file contains one, and only one, deployment selector class. */
|
|
4
|
+
export declare function assertConvexAuthoritySelection(environment: Readonly<Record<string, string>>): ConvexAuthorityKind;
|
|
5
|
+
/** Build a child environment whose only Convex authority comes from the fixed file. */
|
|
6
|
+
export declare function buildConvexCommandEnvironment(inherited: Readonly<Record<string, string | undefined>>, authorityFile: Readonly<Record<string, string>>): Record<string, string>;
|
|
7
|
+
export declare function runConvexCommand(arguments_: readonly string[], options?: {
|
|
8
|
+
cwd?: string;
|
|
9
|
+
inheritedEnvironment?: NodeJS.ProcessEnv;
|
|
10
|
+
}): Promise<number>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import { stat, readFile } from "node:fs/promises";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { parseEnv } from "node:util";
|
|
8
|
+
const AUTHORITY_ENV_FILE = ".env.local";
|
|
9
|
+
const LOCAL_BACKEND_STARTUP_TIMEOUT = "CONVEX_LOCAL_BACKEND_STARTUP_TIMEOUT_SECS";
|
|
10
|
+
const MAX_ENV_FILE_BYTES = 64 * 1024;
|
|
11
|
+
const TOKEN_SELECTORS = ["CONVEX_DEPLOY_KEY", "CONVEX_DEPLOYMENT_TOKEN"];
|
|
12
|
+
const SELF_HOSTED_SELECTORS = ["CONVEX_SELF_HOSTED_URL", "CONVEX_SELF_HOSTED_ADMIN_KEY"];
|
|
13
|
+
const ALLOWED_CONVEX_FILE_NAMES = /* @__PURE__ */ new Set([
|
|
14
|
+
...TOKEN_SELECTORS,
|
|
15
|
+
...SELF_HOSTED_SELECTORS,
|
|
16
|
+
"CONVEX_DEPLOYMENT",
|
|
17
|
+
"CONVEX_SITE_URL",
|
|
18
|
+
"CONVEX_URL"
|
|
19
|
+
]);
|
|
20
|
+
const DEPLOYMENT_SELECTORS = /* @__PURE__ */ new Set([
|
|
21
|
+
...TOKEN_SELECTORS,
|
|
22
|
+
...SELF_HOSTED_SELECTORS,
|
|
23
|
+
"CONVEX_DEPLOYMENT"
|
|
24
|
+
]);
|
|
25
|
+
const PINNED_CONVEX_AUTHORITY_NAMES = [
|
|
26
|
+
...TOKEN_SELECTORS,
|
|
27
|
+
...SELF_HOSTED_SELECTORS,
|
|
28
|
+
"CONVEX_AGENT_MODE",
|
|
29
|
+
"CONVEX_ALLOW_ANONYMOUS",
|
|
30
|
+
"CONVEX_DEPLOYMENT",
|
|
31
|
+
"CONVEX_IMPORT_CHUNK_SIZE",
|
|
32
|
+
"CONVEX_MIN_DOCUMENTS_FOR_INDEX_DELETE_WARNING",
|
|
33
|
+
"CONVEX_OVERRIDE_ACCESS_TOKEN",
|
|
34
|
+
"CONVEX_PROVISION_HOST",
|
|
35
|
+
"CONVEX_RUNNING_LIVE_IN_MONOREPO",
|
|
36
|
+
"CONVEX_SITE_URL",
|
|
37
|
+
"CONVEX_URL",
|
|
38
|
+
"CONVEX_VERBOSE",
|
|
39
|
+
"CONVEX_VERSION_API_ORIGIN",
|
|
40
|
+
"CONVEX_VERSION_OVERRIDE"
|
|
41
|
+
];
|
|
42
|
+
const FORBIDDEN_FILE_BOUND_ARGUMENTS = [
|
|
43
|
+
"--admin-key",
|
|
44
|
+
"--anonymous",
|
|
45
|
+
"--cloud",
|
|
46
|
+
"--configure",
|
|
47
|
+
"--deployment",
|
|
48
|
+
"--deployment-name",
|
|
49
|
+
"--dev-deployment",
|
|
50
|
+
"--env-file",
|
|
51
|
+
"--local",
|
|
52
|
+
"--local-backend-version",
|
|
53
|
+
"--local-dashboard-version",
|
|
54
|
+
"--local-force-upgrade",
|
|
55
|
+
"--override-auth-client",
|
|
56
|
+
"--override-auth-password",
|
|
57
|
+
"--override-auth-url",
|
|
58
|
+
"--override-auth-username",
|
|
59
|
+
"--preview-create",
|
|
60
|
+
"--preview-name",
|
|
61
|
+
"--prod",
|
|
62
|
+
"--project",
|
|
63
|
+
"--team",
|
|
64
|
+
"--type",
|
|
65
|
+
"--url"
|
|
66
|
+
];
|
|
67
|
+
const FILE_BOUND_COMMANDS = /* @__PURE__ */ new Set(["codegen", "deploy", "dev", "env", "run"]);
|
|
68
|
+
const DEPLOYMENT_KEY = /^(?:dev|prod):[^:|\s]+\|\S+$/u;
|
|
69
|
+
const DEPLOYMENT_NAME = /^(?:custom|dev|local|preview|prod):[a-z0-9_-]+$/u;
|
|
70
|
+
function hasValue(environment, name) {
|
|
71
|
+
return typeof environment[name] === "string" && environment[name].length > 0;
|
|
72
|
+
}
|
|
73
|
+
function isAnonymousDeployment(value) {
|
|
74
|
+
const prefix = "anonymous:anonymous-";
|
|
75
|
+
if (!value.startsWith(prefix) || value.length === prefix.length) return false;
|
|
76
|
+
for (const character of value.slice(prefix.length)) {
|
|
77
|
+
const code = character.charCodeAt(0);
|
|
78
|
+
if (character === "/" || character === "\\" || character === ":" || code <= 31 || code === 127) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
export function assertConvexAuthoritySelection(environment) {
|
|
85
|
+
if (Object.keys(environment).some(
|
|
86
|
+
(name) => name.toUpperCase().startsWith("CONVEX_") && !ALLOWED_CONVEX_FILE_NAMES.has(name)
|
|
87
|
+
)) {
|
|
88
|
+
throw new Error("The Convex authority file contains an unsupported Convex setting.");
|
|
89
|
+
}
|
|
90
|
+
const tokens = TOKEN_SELECTORS.filter((name) => hasValue(environment, name));
|
|
91
|
+
const hasDeployment = hasValue(environment, "CONVEX_DEPLOYMENT");
|
|
92
|
+
const selfHosted = SELF_HOSTED_SELECTORS.filter((name) => hasValue(environment, name));
|
|
93
|
+
if (tokens.length > 1 || selfHosted.length === 1) {
|
|
94
|
+
throw new Error("The Convex authority file contains conflicting or incomplete selectors.");
|
|
95
|
+
}
|
|
96
|
+
if (tokens.length === 1 && !DEPLOYMENT_KEY.test(environment[tokens[0]])) {
|
|
97
|
+
throw new Error("The Convex authority file must use a deployment-scoped key.");
|
|
98
|
+
}
|
|
99
|
+
if (hasDeployment && !DEPLOYMENT_NAME.test(environment.CONVEX_DEPLOYMENT) && !isAnonymousDeployment(environment.CONVEX_DEPLOYMENT)) {
|
|
100
|
+
throw new Error("The Convex authority file contains an invalid deployment selector.");
|
|
101
|
+
}
|
|
102
|
+
const selectorClasses = Number(tokens.length === 1) + Number(hasDeployment) + Number(selfHosted.length === 2);
|
|
103
|
+
if (selectorClasses !== 1) {
|
|
104
|
+
throw new Error("The Convex authority file must contain exactly one deployment selector.");
|
|
105
|
+
}
|
|
106
|
+
if (tokens.length === 1) return "deployment-key";
|
|
107
|
+
return hasDeployment ? "deployment-name" : "self-hosted";
|
|
108
|
+
}
|
|
109
|
+
export function buildConvexCommandEnvironment(inherited, authorityFile) {
|
|
110
|
+
assertConvexAuthoritySelection(authorityFile);
|
|
111
|
+
const environment = buildClearedConvexEnvironment(inherited);
|
|
112
|
+
for (const [name, value] of Object.entries(authorityFile)) {
|
|
113
|
+
if (DEPLOYMENT_SELECTORS.has(name)) environment[name] = value;
|
|
114
|
+
}
|
|
115
|
+
if (authorityFile.CONVEX_DEPLOYMENT?.startsWith("anonymous:anonymous-")) {
|
|
116
|
+
environment.CONVEX_AGENT_MODE = "anonymous";
|
|
117
|
+
environment.CONVEX_ALLOW_ANONYMOUS = "true";
|
|
118
|
+
}
|
|
119
|
+
return environment;
|
|
120
|
+
}
|
|
121
|
+
function buildClearedConvexEnvironment(inherited) {
|
|
122
|
+
const localBackendStartupTimeout = inherited[LOCAL_BACKEND_STARTUP_TIMEOUT];
|
|
123
|
+
if (localBackendStartupTimeout) {
|
|
124
|
+
const seconds = Number(localBackendStartupTimeout);
|
|
125
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
126
|
+
throw new Error("The local Convex backend startup timeout must be a positive number.");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const environment = Object.fromEntries(
|
|
130
|
+
Object.entries(inherited).filter(
|
|
131
|
+
(entry) => entry[1] !== void 0 && !entry[0].toUpperCase().startsWith("CONVEX_")
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
for (const name of PINNED_CONVEX_AUTHORITY_NAMES) environment[name] = "";
|
|
135
|
+
if (localBackendStartupTimeout) {
|
|
136
|
+
environment[LOCAL_BACKEND_STARTUP_TIMEOUT] = localBackendStartupTimeout;
|
|
137
|
+
}
|
|
138
|
+
return environment;
|
|
139
|
+
}
|
|
140
|
+
function assertFileBoundArguments(arguments_) {
|
|
141
|
+
for (const argument of arguments_) {
|
|
142
|
+
if (FORBIDDEN_FILE_BOUND_ARGUMENTS.some(
|
|
143
|
+
(name) => argument === name || argument.startsWith(`${name}=`)
|
|
144
|
+
)) {
|
|
145
|
+
throw new Error("Deployment overrides are not supported by this runner.");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function readAuthorityFile(cwd) {
|
|
150
|
+
const path = resolve(cwd, AUTHORITY_ENV_FILE);
|
|
151
|
+
try {
|
|
152
|
+
const file = await stat(path);
|
|
153
|
+
if (!file.isFile() || file.size > MAX_ENV_FILE_BYTES) throw new Error("invalid");
|
|
154
|
+
const source = await readFile(path, "utf8");
|
|
155
|
+
if (source.replaceAll("\r\n", "").includes("\r")) throw new Error("invalid");
|
|
156
|
+
const convexAssignments = /* @__PURE__ */ new Set();
|
|
157
|
+
for (const line of source.split(/\r?\n/u)) {
|
|
158
|
+
const assignment = /^\s*(?:export\s+)?([A-Za-z_]\w*)\s*([=:])/u.exec(line);
|
|
159
|
+
const name = assignment?.[1];
|
|
160
|
+
const separator = assignment?.[2];
|
|
161
|
+
if (name?.toUpperCase().startsWith("CONVEX_")) {
|
|
162
|
+
if (name !== name.toUpperCase() || separator !== "=" || convexAssignments.has(name)) {
|
|
163
|
+
throw new Error("invalid");
|
|
164
|
+
}
|
|
165
|
+
convexAssignments.add(name);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const parsed = parseEnv(source);
|
|
169
|
+
const environment = {};
|
|
170
|
+
for (const [name, value] of Object.entries(parsed)) {
|
|
171
|
+
if (value === void 0) throw new Error("invalid");
|
|
172
|
+
environment[name] = value;
|
|
173
|
+
}
|
|
174
|
+
return environment;
|
|
175
|
+
} catch {
|
|
176
|
+
throw new Error("The Convex authority file is missing, invalid, or too large.");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function usage() {
|
|
180
|
+
return [
|
|
181
|
+
"Run the pinned Convex CLI with one explicit deployment authority.",
|
|
182
|
+
"",
|
|
183
|
+
"Usage:",
|
|
184
|
+
" better-convex-nuxt-convex configure",
|
|
185
|
+
" better-convex-nuxt-convex dev --anonymous [options]",
|
|
186
|
+
" better-convex-nuxt-convex <codegen|deploy|dev|env|run> [options]",
|
|
187
|
+
" better-convex-nuxt-convex deployment select <selector>",
|
|
188
|
+
"",
|
|
189
|
+
"File-bound commands use only .env.local. Configure, anonymous dev, and",
|
|
190
|
+
"deployment select clear inherited and dotenv authority before Convex runs."
|
|
191
|
+
].join("\n");
|
|
192
|
+
}
|
|
193
|
+
export async function runConvexCommand(arguments_, options = {}) {
|
|
194
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
195
|
+
const inherited = options.inheritedEnvironment ?? process.env;
|
|
196
|
+
const [command, ...commandArguments] = arguments_;
|
|
197
|
+
let convexArguments;
|
|
198
|
+
let environment;
|
|
199
|
+
if (command === "configure") {
|
|
200
|
+
if (commandArguments.length > 0) throw new Error("Configure does not accept extra arguments.");
|
|
201
|
+
convexArguments = ["dev", "--configure"];
|
|
202
|
+
environment = buildClearedConvexEnvironment(inherited);
|
|
203
|
+
} else if (command === "deployment" && commandArguments[0] === "select") {
|
|
204
|
+
if (commandArguments.length !== 2 || !commandArguments[1] || commandArguments[1].startsWith("-")) {
|
|
205
|
+
throw new Error("Deployment select requires an explicit selector.");
|
|
206
|
+
}
|
|
207
|
+
convexArguments = [command, ...commandArguments];
|
|
208
|
+
environment = buildClearedConvexEnvironment(inherited);
|
|
209
|
+
} else if (command === "dev" && commandArguments.includes("--anonymous")) {
|
|
210
|
+
if (commandArguments.filter((argument) => argument === "--anonymous").length !== 1) {
|
|
211
|
+
throw new Error("Anonymous development accepts exactly one --anonymous flag.");
|
|
212
|
+
}
|
|
213
|
+
const forwardedArguments = commandArguments.filter((argument) => argument !== "--anonymous");
|
|
214
|
+
assertFileBoundArguments(forwardedArguments);
|
|
215
|
+
convexArguments = [command, ...forwardedArguments];
|
|
216
|
+
environment = buildClearedConvexEnvironment(inherited);
|
|
217
|
+
environment.CONVEX_AGENT_MODE = "anonymous";
|
|
218
|
+
environment.CONVEX_ALLOW_ANONYMOUS = "true";
|
|
219
|
+
} else if (command && FILE_BOUND_COMMANDS.has(command)) {
|
|
220
|
+
assertFileBoundArguments(commandArguments);
|
|
221
|
+
const authorityFile = await readAuthorityFile(cwd);
|
|
222
|
+
const authorityKind = assertConvexAuthoritySelection(authorityFile);
|
|
223
|
+
const deploymentKey = TOKEN_SELECTORS.map((name) => authorityFile[name]).find(Boolean);
|
|
224
|
+
if (command === "deploy" && authorityKind === "deployment-name") {
|
|
225
|
+
throw new Error("Deploy requires a deployment-scoped key or self-hosted authority.");
|
|
226
|
+
}
|
|
227
|
+
if (command === "deploy" && deploymentKey && !deploymentKey.startsWith("prod:")) {
|
|
228
|
+
throw new Error("Deploy requires a production deployment key or self-hosted authority.");
|
|
229
|
+
}
|
|
230
|
+
if (command === "dev" && authorityKind === "deployment-name" && !/^(?:anonymous:anonymous-|dev:|local:)/u.test(authorityFile.CONVEX_DEPLOYMENT)) {
|
|
231
|
+
throw new Error("Dev requires a dev, local, anonymous, or development-key authority.");
|
|
232
|
+
}
|
|
233
|
+
if (command === "dev" && deploymentKey && !deploymentKey.startsWith("dev:")) {
|
|
234
|
+
throw new Error("Dev requires a development deployment key or local authority.");
|
|
235
|
+
}
|
|
236
|
+
environment = buildConvexCommandEnvironment(inherited, authorityFile);
|
|
237
|
+
convexArguments = [command, ...commandArguments];
|
|
238
|
+
} else {
|
|
239
|
+
throw new Error("Unsupported Convex command.");
|
|
240
|
+
}
|
|
241
|
+
const convexCli = resolve(cwd, "node_modules/convex/bin/main.js");
|
|
242
|
+
const result = spawnSync(process.execPath, ["--", convexCli, ...convexArguments], {
|
|
243
|
+
cwd,
|
|
244
|
+
env: environment,
|
|
245
|
+
stdio: "inherit"
|
|
246
|
+
});
|
|
247
|
+
if (result.error || result.status === null) {
|
|
248
|
+
throw new Error("The Convex CLI could not be started or did not exit normally.");
|
|
249
|
+
}
|
|
250
|
+
return result.status;
|
|
251
|
+
}
|
|
252
|
+
let invokedAsScript = false;
|
|
253
|
+
if (process.argv[1]) {
|
|
254
|
+
try {
|
|
255
|
+
invokedAsScript = realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (invokedAsScript) {
|
|
260
|
+
try {
|
|
261
|
+
const arguments_ = process.argv.slice(2);
|
|
262
|
+
if (arguments_.length === 1 && (arguments_[0] === "--help" || arguments_[0] === "-h")) {
|
|
263
|
+
console.log(usage());
|
|
264
|
+
process.exitCode = 0;
|
|
265
|
+
} else {
|
|
266
|
+
process.exitCode = await runConvexCommand(arguments_);
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(
|
|
270
|
+
`[better-convex-nuxt-convex] ${error instanceof Error ? error.message : "failed"}`
|
|
271
|
+
);
|
|
272
|
+
process.exitCode = 1;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ConvexClientHandle } from '@lupinum/better-convex-vue';
|
|
2
|
+
export type { ConvexClientHandle } from '@lupinum/better-convex-vue';
|
|
3
|
+
/** Access the Vue-owned stable, replacement-safe Convex client handle. */
|
|
4
|
+
export declare function useConvex(): ConvexClientHandle;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useConvex as useVueConvex } from "@lupinum/better-convex-vue";
|
|
2
|
+
export function useConvex() {
|
|
3
|
+
if (import.meta.server) {
|
|
4
|
+
throw new Error(
|
|
5
|
+
"[useConvex] Convex client handle is unavailable. This composable is client-only and requires a configured Convex URL."
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
return useVueConvex();
|
|
9
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type UseConvexCall } from '@lupinum/better-convex-vue';
|
|
2
|
+
import type { FunctionReference } from 'convex/server';
|
|
3
|
+
/** Nuxt auto-import facade over the one shared Vue callable lifecycle. */
|
|
4
|
+
export declare function useConvexAction<Action extends FunctionReference<'action'>>(action: Action): UseConvexCall<Action>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useConvexAction as useVueConvexAction
|
|
3
|
+
} from "@lupinum/better-convex-vue";
|
|
4
|
+
import { getFunctionName } from "convex/server";
|
|
5
|
+
import { useNuxtApp } from "#imports";
|
|
6
|
+
import { readConvexRuntimeContext } from "../runtime-context.js";
|
|
7
|
+
import { createCallableDevtoolsEvents } from "../utils/callable-devtools.js";
|
|
8
|
+
import { CALLABLE_OBSERVER_KEY } from "../utils/callable-observer.js";
|
|
9
|
+
export function useConvexAction(action) {
|
|
10
|
+
const runtime = readConvexRuntimeContext(useNuxtApp());
|
|
11
|
+
const events = createCallableDevtoolsEvents({
|
|
12
|
+
operation: "action",
|
|
13
|
+
fnName: getFunctionName(action),
|
|
14
|
+
hasOptimisticUpdate: false,
|
|
15
|
+
getSink: () => runtime?.getDevtoolsSink() ?? null
|
|
16
|
+
});
|
|
17
|
+
return useVueConvexAction(action, { [CALLABLE_OBSERVER_KEY]: events });
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BetterConvexAttachment } from '@lupinum/better-convex-vue/embedded';
|
|
2
|
+
/**
|
|
3
|
+
* Read the frozen, token-free Vue runtime attachment owned by this Nuxt app.
|
|
4
|
+
*
|
|
5
|
+
* Pass this object to a separately bundled Vue application using
|
|
6
|
+
* `createBetterConvex({ attachment })`. It intentionally excludes the
|
|
7
|
+
* broader internal Nuxt runtime context and every credential/provider control.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useConvexAttachment(): BetterConvexAttachment;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
2
|
+
import { readConvexRuntimeContext } from "../runtime-context.js";
|
|
3
|
+
export function useConvexAttachment() {
|
|
4
|
+
if (import.meta.server) {
|
|
5
|
+
throw new Error("[useConvexAttachment] Runtime attachment is available only in the browser.");
|
|
6
|
+
}
|
|
7
|
+
const attachment = readConvexRuntimeContext(useNuxtApp())?.attachment;
|
|
8
|
+
if (!attachment) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"[useConvexAttachment] Convex browser runtime is unavailable. Configure a Convex URL before attaching an embedded application."
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return attachment;
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InferRegisteredConvexAuthClient } from '../auth-client/index.js';
|
|
2
|
+
import type { UseConvexAuthReturn } from '../utils/auth-contract.js';
|
|
3
|
+
export type { UseConvexAuthReturn } from '../utils/auth-contract.js';
|
|
4
|
+
/**
|
|
5
|
+
* Access Convex authentication state and the inferred integrated Better Auth
|
|
6
|
+
* client. The client is browser-owned, so it is `null` during SSR/early setup.
|
|
7
|
+
* Synchronous Better Auth methods stay synchronous; PromiseLike operations do
|
|
8
|
+
* not settle until their canonical provider session is accepted by Convex.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useConvexAuth(): UseConvexAuthReturn<InferRegisteredConvexAuthClient>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { computed, readonly, useNuxtApp, useState } from "#imports";
|
|
2
|
+
import { identityKeyOf, identityUser } from "../auth/auth-identity.js";
|
|
3
|
+
import { ConvexCallError } from "../errors/index.js";
|
|
4
|
+
import { readConvexRuntimeContext } from "../runtime-context.js";
|
|
5
|
+
import { useConvexIdentityState } from "../utils/auth-identity-state.js";
|
|
6
|
+
import { deriveConvexAuthStatus } from "../utils/auth-status.js";
|
|
7
|
+
export function useConvexAuth() {
|
|
8
|
+
const nuxtApp = useNuxtApp();
|
|
9
|
+
const identity = useConvexIdentityState();
|
|
10
|
+
const user = computed(() => identityUser(identity.value));
|
|
11
|
+
const authError = useState("convex:authError", () => null);
|
|
12
|
+
const pending = useState("convex:pending", () => import.meta.client);
|
|
13
|
+
const coordinator = readConvexRuntimeContext(nuxtApp)?.getAuthController() ?? void 0;
|
|
14
|
+
const status = computed(
|
|
15
|
+
() => deriveConvexAuthStatus({
|
|
16
|
+
authEnabled: true,
|
|
17
|
+
settled: !pending.value,
|
|
18
|
+
identityKey: identityKeyOf(identity.value),
|
|
19
|
+
error: authError.value ? new ConvexCallError({ kind: "authentication", message: authError.value }) : null
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
const isPending = coordinator ? coordinator.isPending : computed(() => pending.value);
|
|
23
|
+
const error = computed(
|
|
24
|
+
() => authError.value ? new ConvexCallError({ kind: "authentication", message: authError.value }) : void 0
|
|
25
|
+
);
|
|
26
|
+
return {
|
|
27
|
+
status,
|
|
28
|
+
isPending,
|
|
29
|
+
user: readonly(user),
|
|
30
|
+
error,
|
|
31
|
+
client: coordinator?.client ?? null,
|
|
32
|
+
ready: async (options) => {
|
|
33
|
+
if (!coordinator) return status.value;
|
|
34
|
+
return coordinator.ready(options);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ConvexRuntimeConfig } from '../utils/runtime-config.js';
|
|
2
|
+
export type { ConvexRuntimeConfig } from '../utils/runtime-config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Read the resolved Convex connection origins.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const config = useConvexConfig()
|
|
9
|
+
* console.log(config.url, config.siteUrl)
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function useConvexConfig(): ConvexRuntimeConfig;
|