workos 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +3 -0
- package/dist/bin.js.map +1 -1
- package/dist/lib/version-check.d.ts +6 -0
- package/dist/lib/version-check.js +45 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/utils/exec-file.d.ts +15 -0
- package/dist/utils/exec-file.js +38 -0
- package/dist/utils/exec-file.js.map +1 -0
- package/package.json +8 -2
- package/skills/workos-authkit-nextjs/SKILL.md +75 -10
- package/skills/workos-authkit-tanstack-start/SKILL.md +184 -27
package/dist/bin.js
CHANGED
|
@@ -11,6 +11,7 @@ import { getConfig } from './lib/settings.js';
|
|
|
11
11
|
import yargs from 'yargs';
|
|
12
12
|
import { hideBin } from 'yargs/helpers';
|
|
13
13
|
import { ensureAuthenticated } from './lib/ensure-auth.js';
|
|
14
|
+
import { checkForUpdates } from './lib/version-check.js';
|
|
14
15
|
const NODE_VERSION_RANGE = getConfig().nodeVersion;
|
|
15
16
|
// Have to run this above the other imports because they are importing clack that
|
|
16
17
|
// has the problematic imports.
|
|
@@ -110,6 +111,8 @@ const installerOptions = {
|
|
|
110
111
|
type: 'boolean',
|
|
111
112
|
},
|
|
112
113
|
};
|
|
114
|
+
// Check for updates (blocks up to 500ms)
|
|
115
|
+
await checkForUpdates();
|
|
113
116
|
yargs(hideBin(process.argv))
|
|
114
117
|
.env('WORKOS_INSTALLER')
|
|
115
118
|
.command('login', 'Authenticate with WorkOS', {}, async () => {
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\n// Load .env.local for local development when --local flag is used\nif (process.argv.includes('--local') || process.env.INSTALLER_DEV) {\n const { config } = await import('dotenv');\n // bin.ts compiles to dist/bin.js, so go up one level to find .env.local\n config({ path: new URL('../.env.local', import.meta.url).pathname });\n}\n\nimport { satisfies } from 'semver';\nimport { red } from './utils/logging.js';\nimport { getConfig } from './lib/settings.js';\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport chalk from 'chalk';\nimport { ensureAuthenticated } from './lib/ensure-auth.js';\n\nconst NODE_VERSION_RANGE = getConfig().nodeVersion;\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n red(\n `WorkOS AuthKit installer requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`,\n );\n process.exit(1);\n}\n\nimport { isNonInteractiveEnvironment } from './utils/environment.js';\nimport clack from './utils/clack.js';\n\n// Shared options for wizard commands (default and dashboard)\n/**\n * Wrap a command handler with authentication check.\n * Ensures valid auth before executing the handler.\n * Respects --skip-auth flag for CI/testing.\n */\nfunction withAuth<T>(handler: (argv: T) => Promise<void>): (argv: T) => Promise<void> {\n return async (argv: T) => {\n if (!(argv as { skipAuth?: boolean }).skipAuth) {\n await ensureAuthenticated();\n }\n await handler(argv);\n };\n}\n\nconst installerOptions = {\n direct: {\n alias: 'D',\n default: false,\n describe: 'Use your own Anthropic API key (bypass llm-gateway)',\n type: 'boolean' as const,\n },\n debug: {\n default: false,\n describe: 'Enable verbose logging',\n type: 'boolean' as const,\n },\n // Hidden dev/automation flags (use env vars)\n local: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n ci: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n 'skip-auth': {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n 'api-key': {\n type: 'string' as const,\n hidden: true,\n },\n 'client-id': {\n type: 'string' as const,\n hidden: true,\n },\n inspect: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n // User-facing flags\n 'homepage-url': {\n describe: 'App homepage URL for WorkOS (defaults to http://localhost:{port})',\n type: 'string' as const,\n },\n 'redirect-uri': {\n describe: 'Redirect URI for WorkOS callback (defaults to framework convention)',\n type: 'string' as const,\n },\n 'no-validate': {\n default: false,\n describe: 'Skip post-installation validation (includes build check)',\n type: 'boolean' as const,\n },\n 'install-dir': {\n describe: 'Directory to install WorkOS AuthKit in',\n type: 'string' as const,\n },\n integration: {\n describe: 'Integration to set up',\n choices: ['nextjs', 'react', 'tanstack-start', 'react-router', 'vanilla-js'] as const,\n type: 'string' as const,\n },\n 'force-install': {\n default: false,\n describe: 'Force install packages even if peer dependency checks fail',\n type: 'boolean' as const,\n },\n dashboard: {\n alias: 'd',\n default: false,\n describe: 'Run with visual dashboard mode',\n type: 'boolean' as const,\n },\n};\n\nyargs(hideBin(process.argv))\n .env('WORKOS_INSTALLER')\n .command('login', 'Authenticate with WorkOS', {}, async () => {\n const { runLogin } = await import('./commands/login.js');\n await runLogin();\n process.exit(0);\n })\n .command('logout', 'Remove stored credentials', {}, async () => {\n const { runLogout } = await import('./commands/logout.js');\n await runLogout();\n })\n .command(\n 'install-skill',\n 'Install bundled AuthKit skills to coding agents',\n (yargs) => {\n return yargs\n .option('list', {\n alias: 'l',\n type: 'boolean',\n description: 'List available skills without installing',\n })\n .option('skill', {\n alias: 's',\n type: 'array',\n string: true,\n description: 'Install specific skill(s)',\n })\n .option('agent', {\n alias: 'a',\n type: 'array',\n string: true,\n description: 'Target specific agent(s): claude-code, codex, cursor, goose',\n });\n },\n withAuth(async (argv) => {\n const { runInstallSkill } = await import('./commands/install-skill.js');\n await runInstallSkill({\n list: argv.list as boolean | undefined,\n skill: argv.skill as string[] | undefined,\n agent: argv.agent as string[] | undefined,\n });\n }),\n )\n .command(\n 'install',\n 'Install WorkOS AuthKit into your project',\n (yargs) => yargs.options(installerOptions),\n withAuth(async (argv) => {\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall(argv);\n }),\n )\n .command(\n 'dashboard',\n false, // hidden from help\n (yargs) => yargs.options(installerOptions),\n withAuth(async (argv) => {\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall({ ...argv, dashboard: true });\n }),\n )\n .command(\n ['$0'],\n 'WorkOS AuthKit CLI',\n (yargs) => yargs,\n async () => {\n // Non-TTY: show help\n if (isNonInteractiveEnvironment()) {\n yargs(hideBin(process.argv)).showHelp();\n return;\n }\n\n // TTY: ask if user wants to run installer\n const shouldInstall = await clack.confirm({\n message: 'Run the AuthKit installer?',\n });\n\n if (clack.isCancel(shouldInstall) || !shouldInstall) {\n process.exit(0);\n }\n\n // Auth check happens HERE, after user confirms\n await ensureAuthenticated();\n\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall({ dashboard: false } as any);\n process.exit(0);\n },\n )\n .strict()\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v')\n .wrap(process.stdout.isTTY && process.stdout.columns ? process.stdout.columns : 80).argv;\n"]}
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\n// Load .env.local for local development when --local flag is used\nif (process.argv.includes('--local') || process.env.INSTALLER_DEV) {\n const { config } = await import('dotenv');\n // bin.ts compiles to dist/bin.js, so go up one level to find .env.local\n config({ path: new URL('../.env.local', import.meta.url).pathname });\n}\n\nimport { satisfies } from 'semver';\nimport { red } from './utils/logging.js';\nimport { getConfig } from './lib/settings.js';\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport chalk from 'chalk';\nimport { ensureAuthenticated } from './lib/ensure-auth.js';\nimport { checkForUpdates } from './lib/version-check.js';\n\nconst NODE_VERSION_RANGE = getConfig().nodeVersion;\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n red(\n `WorkOS AuthKit installer requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`,\n );\n process.exit(1);\n}\n\nimport { isNonInteractiveEnvironment } from './utils/environment.js';\nimport clack from './utils/clack.js';\n\n// Shared options for wizard commands (default and dashboard)\n/**\n * Wrap a command handler with authentication check.\n * Ensures valid auth before executing the handler.\n * Respects --skip-auth flag for CI/testing.\n */\nfunction withAuth<T>(handler: (argv: T) => Promise<void>): (argv: T) => Promise<void> {\n return async (argv: T) => {\n if (!(argv as { skipAuth?: boolean }).skipAuth) {\n await ensureAuthenticated();\n }\n await handler(argv);\n };\n}\n\nconst installerOptions = {\n direct: {\n alias: 'D',\n default: false,\n describe: 'Use your own Anthropic API key (bypass llm-gateway)',\n type: 'boolean' as const,\n },\n debug: {\n default: false,\n describe: 'Enable verbose logging',\n type: 'boolean' as const,\n },\n // Hidden dev/automation flags (use env vars)\n local: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n ci: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n 'skip-auth': {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n 'api-key': {\n type: 'string' as const,\n hidden: true,\n },\n 'client-id': {\n type: 'string' as const,\n hidden: true,\n },\n inspect: {\n default: false,\n type: 'boolean' as const,\n hidden: true,\n },\n // User-facing flags\n 'homepage-url': {\n describe: 'App homepage URL for WorkOS (defaults to http://localhost:{port})',\n type: 'string' as const,\n },\n 'redirect-uri': {\n describe: 'Redirect URI for WorkOS callback (defaults to framework convention)',\n type: 'string' as const,\n },\n 'no-validate': {\n default: false,\n describe: 'Skip post-installation validation (includes build check)',\n type: 'boolean' as const,\n },\n 'install-dir': {\n describe: 'Directory to install WorkOS AuthKit in',\n type: 'string' as const,\n },\n integration: {\n describe: 'Integration to set up',\n choices: ['nextjs', 'react', 'tanstack-start', 'react-router', 'vanilla-js'] as const,\n type: 'string' as const,\n },\n 'force-install': {\n default: false,\n describe: 'Force install packages even if peer dependency checks fail',\n type: 'boolean' as const,\n },\n dashboard: {\n alias: 'd',\n default: false,\n describe: 'Run with visual dashboard mode',\n type: 'boolean' as const,\n },\n};\n\n// Check for updates (blocks up to 500ms)\nawait checkForUpdates();\n\nyargs(hideBin(process.argv))\n .env('WORKOS_INSTALLER')\n .command('login', 'Authenticate with WorkOS', {}, async () => {\n const { runLogin } = await import('./commands/login.js');\n await runLogin();\n process.exit(0);\n })\n .command('logout', 'Remove stored credentials', {}, async () => {\n const { runLogout } = await import('./commands/logout.js');\n await runLogout();\n })\n .command(\n 'install-skill',\n 'Install bundled AuthKit skills to coding agents',\n (yargs) => {\n return yargs\n .option('list', {\n alias: 'l',\n type: 'boolean',\n description: 'List available skills without installing',\n })\n .option('skill', {\n alias: 's',\n type: 'array',\n string: true,\n description: 'Install specific skill(s)',\n })\n .option('agent', {\n alias: 'a',\n type: 'array',\n string: true,\n description: 'Target specific agent(s): claude-code, codex, cursor, goose',\n });\n },\n withAuth(async (argv) => {\n const { runInstallSkill } = await import('./commands/install-skill.js');\n await runInstallSkill({\n list: argv.list as boolean | undefined,\n skill: argv.skill as string[] | undefined,\n agent: argv.agent as string[] | undefined,\n });\n }),\n )\n .command(\n 'install',\n 'Install WorkOS AuthKit into your project',\n (yargs) => yargs.options(installerOptions),\n withAuth(async (argv) => {\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall(argv);\n }),\n )\n .command(\n 'dashboard',\n false, // hidden from help\n (yargs) => yargs.options(installerOptions),\n withAuth(async (argv) => {\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall({ ...argv, dashboard: true });\n }),\n )\n .command(\n ['$0'],\n 'WorkOS AuthKit CLI',\n (yargs) => yargs,\n async () => {\n // Non-TTY: show help\n if (isNonInteractiveEnvironment()) {\n yargs(hideBin(process.argv)).showHelp();\n return;\n }\n\n // TTY: ask if user wants to run installer\n const shouldInstall = await clack.confirm({\n message: 'Run the AuthKit installer?',\n });\n\n if (clack.isCancel(shouldInstall) || !shouldInstall) {\n process.exit(0);\n }\n\n // Auth check happens HERE, after user confirms\n await ensureAuthenticated();\n\n const { handleInstall } = await import('./commands/install.js');\n await handleInstall({ dashboard: false } as any);\n process.exit(0);\n },\n )\n .strict()\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v')\n .wrap(process.stdout.isTTY && process.stdout.columns ? process.stdout.columns : 80).argv;\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { lt, valid } from 'semver';
|
|
2
|
+
import { yellow, dim } from '../utils/logging.js';
|
|
3
|
+
import { getVersion } from './settings.js';
|
|
4
|
+
const NPM_REGISTRY_URL = 'https://registry.npmjs.org/workos/latest';
|
|
5
|
+
const TIMEOUT_MS = 500;
|
|
6
|
+
let hasWarned = false;
|
|
7
|
+
/**
|
|
8
|
+
* Check npm registry for latest version and warn if outdated.
|
|
9
|
+
* Runs asynchronously, fails silently on any error.
|
|
10
|
+
* Safe to call without awaiting (fire-and-forget).
|
|
11
|
+
*/
|
|
12
|
+
export async function checkForUpdates() {
|
|
13
|
+
if (hasWarned)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
17
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok)
|
|
20
|
+
return;
|
|
21
|
+
const data = (await response.json());
|
|
22
|
+
const latestVersion = data.version;
|
|
23
|
+
const currentVersion = getVersion();
|
|
24
|
+
// Validate both versions are valid semver
|
|
25
|
+
if (!valid(latestVersion) || !valid(currentVersion))
|
|
26
|
+
return;
|
|
27
|
+
// Only warn if current < latest
|
|
28
|
+
if (lt(currentVersion, latestVersion)) {
|
|
29
|
+
hasWarned = true;
|
|
30
|
+
yellow(`Update available: ${currentVersion} → ${latestVersion}`);
|
|
31
|
+
dim(`Run: npx workos@latest`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Silently ignore all errors (timeout, network, parse, etc.)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reset warning state (for testing).
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export function _resetWarningState() {
|
|
43
|
+
hasWarned = false;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/lib/version-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,gBAAgB,GAAG,0CAA0C,CAAC;AACpE,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,IAAI,SAAS,GAAG,KAAK,CAAC;AAMtB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,SAAS;QAAE,OAAO;IAEtB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,gBAAgB,EAAE;YAC7C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC;SACxC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO;QAEzB,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,MAAM,cAAc,GAAG,UAAU,EAAE,CAAC;QAEpC,0CAA0C;QAC1C,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;YAAE,OAAO;QAE5D,gCAAgC;QAChC,IAAI,EAAE,CAAC,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC;YACtC,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,CAAC,qBAAqB,cAAc,MAAM,aAAa,EAAE,CAAC,CAAC;YACjE,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,SAAS,GAAG,KAAK,CAAC;AACpB,CAAC","sourcesContent":["import { lt, valid } from 'semver';\nimport { yellow, dim } from '../utils/logging.js';\nimport { getVersion } from './settings.js';\n\nconst NPM_REGISTRY_URL = 'https://registry.npmjs.org/workos/latest';\nconst TIMEOUT_MS = 500;\n\nlet hasWarned = false;\n\ninterface NpmPackageInfo {\n version: string;\n}\n\n/**\n * Check npm registry for latest version and warn if outdated.\n * Runs asynchronously, fails silently on any error.\n * Safe to call without awaiting (fire-and-forget).\n */\nexport async function checkForUpdates(): Promise<void> {\n if (hasWarned) return;\n\n try {\n const response = await fetch(NPM_REGISTRY_URL, {\n signal: AbortSignal.timeout(TIMEOUT_MS),\n });\n\n if (!response.ok) return;\n\n const data = (await response.json()) as NpmPackageInfo;\n const latestVersion = data.version;\n const currentVersion = getVersion();\n\n // Validate both versions are valid semver\n if (!valid(latestVersion) || !valid(currentVersion)) return;\n\n // Only warn if current < latest\n if (lt(currentVersion, latestVersion)) {\n hasWarned = true;\n yellow(`Update available: ${currentVersion} → ${latestVersion}`);\n dim(`Run: npx workos@latest`);\n }\n } catch {\n // Silently ignore all errors (timeout, network, parse, etc.)\n }\n}\n\n/**\n * Reset warning state (for testing).\n * @internal\n */\nexport function _resetWarningState(): void {\n hasWarned = false;\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ExecResult {
|
|
2
|
+
status: number;
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ExecOptions {
|
|
7
|
+
cwd?: string;
|
|
8
|
+
timeout?: number;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Execute a command without throwing on non-zero exit codes.
|
|
13
|
+
* Returns { status, stdout, stderr } for all outcomes.
|
|
14
|
+
*/
|
|
15
|
+
export declare function execFileNoThrow(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Execute a command without throwing on non-zero exit codes.
|
|
4
|
+
* Returns { status, stdout, stderr } for all outcomes.
|
|
5
|
+
*/
|
|
6
|
+
export function execFileNoThrow(command, args, options = {}) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
const child = spawn(command, args, {
|
|
9
|
+
cwd: options.cwd,
|
|
10
|
+
env: options.env ?? process.env,
|
|
11
|
+
timeout: options.timeout,
|
|
12
|
+
shell: false,
|
|
13
|
+
});
|
|
14
|
+
let stdout = '';
|
|
15
|
+
let stderr = '';
|
|
16
|
+
child.stdout?.on('data', (data) => {
|
|
17
|
+
stdout += data.toString();
|
|
18
|
+
});
|
|
19
|
+
child.stderr?.on('data', (data) => {
|
|
20
|
+
stderr += data.toString();
|
|
21
|
+
});
|
|
22
|
+
child.on('close', (code) => {
|
|
23
|
+
resolve({
|
|
24
|
+
status: code ?? 1,
|
|
25
|
+
stdout,
|
|
26
|
+
stderr,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
child.on('error', (err) => {
|
|
30
|
+
resolve({
|
|
31
|
+
status: 1,
|
|
32
|
+
stdout,
|
|
33
|
+
stderr: err.message,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=exec-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-file.js","sourceRoot":"","sources":["../../src/utils/exec-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAc3C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,IAAc,EAAE,UAAuB,EAAE;IACxF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;YAC/B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,OAAO,CAAC;gBACN,MAAM,EAAE,IAAI,IAAI,CAAC;gBACjB,MAAM;gBACN,MAAM;aACP,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC;gBACN,MAAM,EAAE,CAAC;gBACT,MAAM;gBACN,MAAM,EAAE,GAAG,CAAC,OAAO;aACpB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { spawn } from 'node:child_process';\n\nexport interface ExecResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ExecOptions {\n cwd?: string;\n timeout?: number;\n env?: NodeJS.ProcessEnv;\n}\n\n/**\n * Execute a command without throwing on non-zero exit codes.\n * Returns { status, stdout, stderr } for all outcomes.\n */\nexport function execFileNoThrow(command: string, args: string[], options: ExecOptions = {}): Promise<ExecResult> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n cwd: options.cwd,\n env: options.env ?? process.env,\n timeout: options.timeout,\n shell: false,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n child.on('close', (code) => {\n resolve({\n status: code ?? 1,\n stdout,\n stderr,\n });\n });\n\n child.on('error', (err) => {\n resolve({\n status: 1,\n stdout,\n stderr: err.message,\n });\n });\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workos",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The Official Workos CLI",
|
|
6
6
|
"repository": {
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"@vitest/coverage-v8": "^4.0.18",
|
|
64
64
|
"@vitest/ui": "^4.0.18",
|
|
65
65
|
"dotenv": "^17.2.3",
|
|
66
|
+
"p-limit": "^7.2.0",
|
|
66
67
|
"prettier": "^3.8.0",
|
|
67
68
|
"tsx": "^4.20.3",
|
|
68
69
|
"typescript": "^5.9.3",
|
|
@@ -86,6 +87,11 @@
|
|
|
86
87
|
"test": "vitest run",
|
|
87
88
|
"test:watch": "vitest",
|
|
88
89
|
"test:coverage": "vitest run --coverage",
|
|
89
|
-
"typecheck": "tsc --noEmit"
|
|
90
|
+
"typecheck": "tsc --noEmit",
|
|
91
|
+
"eval": "tsx tests/evals/index.ts",
|
|
92
|
+
"eval:history": "tsx tests/evals/index.ts history",
|
|
93
|
+
"eval:compare": "tsx tests/evals/index.ts compare",
|
|
94
|
+
"eval:logs": "tsx tests/evals/index.ts logs",
|
|
95
|
+
"eval:show": "tsx tests/evals/index.ts show"
|
|
90
96
|
}
|
|
91
97
|
}
|
|
@@ -55,6 +55,46 @@ Next.js version?
|
|
|
55
55
|
|
|
56
56
|
Middleware/proxy code: See README for `authkitMiddleware()` export pattern.
|
|
57
57
|
|
|
58
|
+
### Existing Middleware (IMPORTANT)
|
|
59
|
+
|
|
60
|
+
If `middleware.ts` already exists with custom logic (rate limiting, logging, headers, etc.), use the **`authkit()` composable function** instead of `authkitMiddleware`.
|
|
61
|
+
|
|
62
|
+
**Pattern for composing with existing middleware:**
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
66
|
+
import { authkit, handleAuthkitHeaders } from '@workos-inc/authkit-nextjs';
|
|
67
|
+
|
|
68
|
+
export default async function middleware(request: NextRequest) {
|
|
69
|
+
// 1. Get auth session and headers from AuthKit
|
|
70
|
+
const { session, headers, authorizationUrl } = await authkit(request);
|
|
71
|
+
const { pathname } = request.nextUrl;
|
|
72
|
+
|
|
73
|
+
// 2. === YOUR EXISTING MIDDLEWARE LOGIC ===
|
|
74
|
+
// Rate limiting, logging, custom headers, etc.
|
|
75
|
+
const rateLimitResult = checkRateLimit(request);
|
|
76
|
+
if (!rateLimitResult.allowed) {
|
|
77
|
+
return new NextResponse('Too Many Requests', { status: 429 });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 3. Protect routes - redirect to auth if needed
|
|
81
|
+
if (pathname.startsWith('/dashboard') && !session.user && authorizationUrl) {
|
|
82
|
+
return handleAuthkitHeaders(request, headers, { redirect: authorizationUrl });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 4. Continue with AuthKit headers properly handled
|
|
86
|
+
return handleAuthkitHeaders(request, headers);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Key functions:**
|
|
91
|
+
|
|
92
|
+
- `authkit(request)` - Returns `{ session, headers, authorizationUrl }` for composition
|
|
93
|
+
- `handleAuthkitHeaders(request, headers, options?)` - Ensures AuthKit headers pass through correctly
|
|
94
|
+
- For rewrites, use `partitionAuthkitHeaders()` and `applyResponseHeaders()` (see README)
|
|
95
|
+
|
|
96
|
+
**Critical:** Always return via `handleAuthkitHeaders()` to ensure `withAuth()` works in pages.
|
|
97
|
+
|
|
58
98
|
## Step 5: Create Callback Route
|
|
59
99
|
|
|
60
100
|
Parse `NEXT_PUBLIC_WORKOS_REDIRECT_URI` to determine route path:
|
|
@@ -78,33 +118,58 @@ export const GET = handleAuth();
|
|
|
78
118
|
|
|
79
119
|
Check README for exact usage. If build fails with "cookies outside request scope", the handler is likely missing async/await.
|
|
80
120
|
|
|
81
|
-
## Step 6: Provider Setup
|
|
121
|
+
## Step 6: Provider Setup (REQUIRED)
|
|
122
|
+
|
|
123
|
+
**CRITICAL:** You MUST wrap the app in `AuthKitProvider` in `app/layout.tsx`.
|
|
124
|
+
|
|
125
|
+
This is required for:
|
|
126
|
+
|
|
127
|
+
- Client-side auth state via `useAuth()` hook
|
|
128
|
+
- Consistent auth UX across client/server boundaries
|
|
129
|
+
- Proper migration from Auth0 (which uses client-side auth)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
// app/layout.tsx
|
|
133
|
+
import { AuthKitProvider } from '@workos-inc/authkit-nextjs';
|
|
134
|
+
|
|
135
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
136
|
+
return (
|
|
137
|
+
<html lang="en">
|
|
138
|
+
<body>
|
|
139
|
+
<AuthKitProvider>{children}</AuthKitProvider>
|
|
140
|
+
</body>
|
|
141
|
+
</html>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Check README for exact import path - it may be a subpath export like `@workos-inc/authkit-nextjs/components`.
|
|
82
147
|
|
|
83
|
-
|
|
148
|
+
**Do NOT skip this step** even if using server-side auth patterns elsewhere.
|
|
84
149
|
|
|
85
150
|
## Step 7: UI Integration
|
|
86
151
|
|
|
87
152
|
Add auth UI to `app/page.tsx` using SDK functions. See README for `getUser`, `getSignInUrl`, `signOut` usage.
|
|
88
153
|
|
|
89
|
-
## Verification Checklist
|
|
154
|
+
## Verification Checklist (ALL MUST PASS)
|
|
90
155
|
|
|
91
|
-
Run these commands to confirm integration
|
|
156
|
+
Run these commands to confirm integration. **Do not mark complete until all pass:**
|
|
92
157
|
|
|
93
158
|
```bash
|
|
94
|
-
# Check middleware/proxy exists (one should match)
|
|
159
|
+
# 1. Check middleware/proxy exists (one should match)
|
|
95
160
|
ls proxy.ts middleware.ts src/proxy.ts src/middleware.ts 2>/dev/null
|
|
96
161
|
|
|
97
|
-
# Check
|
|
98
|
-
grep
|
|
162
|
+
# 2. CRITICAL: Check AuthKitProvider is in layout (REQUIRED)
|
|
163
|
+
grep "AuthKitProvider" app/layout.tsx || echo "FAIL: AuthKitProvider missing from layout"
|
|
99
164
|
|
|
100
|
-
# Check callback route exists
|
|
165
|
+
# 3. Check callback route exists
|
|
101
166
|
find app -name "route.ts" -path "*/callback/*"
|
|
102
167
|
|
|
103
|
-
# Build succeeds
|
|
168
|
+
# 4. Build succeeds
|
|
104
169
|
npm run build
|
|
105
170
|
```
|
|
106
171
|
|
|
107
|
-
|
|
172
|
+
**If check #2 fails:** Go back to Step 6 and add AuthKitProvider. This is not optional.
|
|
108
173
|
|
|
109
174
|
## Error Recovery
|
|
110
175
|
|
|
@@ -12,9 +12,9 @@ description: Integrate WorkOS AuthKit with TanStack Start applications. Full-sta
|
|
|
12
12
|
├── Extract package name from install command
|
|
13
13
|
└── README is source of truth for ALL code patterns
|
|
14
14
|
|
|
15
|
-
2.
|
|
16
|
-
├──
|
|
17
|
-
└── app
|
|
15
|
+
2. Detect directory structure
|
|
16
|
+
├── src/ (TanStack Start v1.132+, default)
|
|
17
|
+
└── app/ (legacy vinxi-based projects)
|
|
18
18
|
|
|
19
19
|
3. Follow README install/setup exactly
|
|
20
20
|
└── Do not invent commands or patterns
|
|
@@ -28,7 +28,7 @@ WebFetch: `https://github.com/workos/authkit-tanstack-start/blob/main/README.md`
|
|
|
28
28
|
|
|
29
29
|
From README, extract:
|
|
30
30
|
|
|
31
|
-
1. Package name
|
|
31
|
+
1. Package name: `@workos/authkit-tanstack-react-start`
|
|
32
32
|
2. Use that exact name for all imports
|
|
33
33
|
|
|
34
34
|
**README overrides this skill if conflict.**
|
|
@@ -37,9 +37,38 @@ From README, extract:
|
|
|
37
37
|
|
|
38
38
|
- [ ] README fetched and package name extracted
|
|
39
39
|
- [ ] `@tanstack/start` or `@tanstack/react-start` in package.json
|
|
40
|
-
- [ ] `app
|
|
40
|
+
- [ ] Identify directory structure: `src/` (modern) or `app/` (legacy)
|
|
41
41
|
- [ ] Environment variables set (see below)
|
|
42
42
|
|
|
43
|
+
## Directory Structure Detection
|
|
44
|
+
|
|
45
|
+
**Modern TanStack Start (v1.132+)** uses `src/`:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
src/
|
|
49
|
+
├── start.ts # Middleware config (CRITICAL)
|
|
50
|
+
├── router.tsx # Router setup
|
|
51
|
+
├── routes/
|
|
52
|
+
│ ├── __root.tsx # Root layout
|
|
53
|
+
│ ├── api.auth.callback.tsx # OAuth callback (flat route)
|
|
54
|
+
│ └── ...
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Legacy (vinxi-based)** uses `app/`:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
app/
|
|
61
|
+
├── start.ts or router.tsx
|
|
62
|
+
├── routes/
|
|
63
|
+
│ └── api/auth/callback.tsx # OAuth callback (nested route)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Detection:**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ls src/routes 2>/dev/null && echo "Modern (src/)" || echo "Legacy (app/)"
|
|
70
|
+
```
|
|
71
|
+
|
|
43
72
|
## Environment Variables
|
|
44
73
|
|
|
45
74
|
| Variable | Format | Required |
|
|
@@ -51,56 +80,184 @@ From README, extract:
|
|
|
51
80
|
|
|
52
81
|
Generate password if missing: `openssl rand -base64 32`
|
|
53
82
|
|
|
83
|
+
Default redirect URI: `http://localhost:3000/api/auth/callback`
|
|
84
|
+
|
|
54
85
|
## Middleware Configuration (CRITICAL)
|
|
55
86
|
|
|
56
|
-
**authkitMiddleware MUST be configured or auth will fail.**
|
|
87
|
+
**authkitMiddleware MUST be configured or auth will fail silently.**
|
|
57
88
|
|
|
58
|
-
|
|
89
|
+
Create or update `src/start.ts` (or `app/start.ts` for legacy):
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { authkitMiddleware } from '@workos/authkit-tanstack-react-start';
|
|
93
|
+
|
|
94
|
+
export default {
|
|
95
|
+
requestMiddleware: [authkitMiddleware()],
|
|
96
|
+
};
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Alternative pattern with createStart:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { createStart } from '@tanstack/react-start';
|
|
103
|
+
import { authkitMiddleware } from '@workos/authkit-tanstack-react-start';
|
|
104
|
+
|
|
105
|
+
export default createStart({
|
|
106
|
+
requestMiddleware: [authkitMiddleware()],
|
|
107
|
+
});
|
|
108
|
+
```
|
|
59
109
|
|
|
60
110
|
### Verification Checklist
|
|
61
111
|
|
|
62
|
-
- [ ] `authkitMiddleware` imported from
|
|
63
|
-
- [ ]
|
|
64
|
-
- [ ]
|
|
112
|
+
- [ ] `authkitMiddleware` imported from `@workos/authkit-tanstack-react-start`
|
|
113
|
+
- [ ] Middleware in `requestMiddleware` array
|
|
114
|
+
- [ ] File exports the config (default export or named `startInstance`)
|
|
65
115
|
|
|
66
|
-
Verify: `grep "authkitMiddleware"
|
|
116
|
+
Verify: `grep -r "authkitMiddleware" src/ app/ 2>/dev/null`
|
|
117
|
+
|
|
118
|
+
## Callback Route (CRITICAL)
|
|
119
|
+
|
|
120
|
+
Path must match `WORKOS_REDIRECT_URI`. For `/api/auth/callback`:
|
|
121
|
+
|
|
122
|
+
**Modern (flat routes):** `src/routes/api.auth.callback.tsx`
|
|
123
|
+
**Legacy (nested routes):** `app/routes/api/auth/callback.tsx`
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
127
|
+
import { handleCallbackRoute } from '@workos/authkit-tanstack-react-start';
|
|
128
|
+
|
|
129
|
+
export const Route = createFileRoute('/api/auth/callback')({
|
|
130
|
+
server: {
|
|
131
|
+
handlers: {
|
|
132
|
+
GET: handleCallbackRoute(),
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
```
|
|
67
137
|
|
|
68
|
-
|
|
138
|
+
**Key points:**
|
|
69
139
|
|
|
70
|
-
|
|
140
|
+
- Use `handleCallbackRoute()` - do not write custom OAuth logic
|
|
141
|
+
- Route path string must match the URI path exactly
|
|
142
|
+
- This is a server-only route (no component needed)
|
|
71
143
|
|
|
72
|
-
##
|
|
144
|
+
## Protected Routes
|
|
73
145
|
|
|
74
|
-
|
|
146
|
+
Use `getAuth()` in route loaders to check authentication:
|
|
75
147
|
|
|
76
|
-
|
|
77
|
-
|
|
148
|
+
```typescript
|
|
149
|
+
import { createFileRoute, redirect } from '@tanstack/react-router';
|
|
150
|
+
import { getAuth, getSignInUrl } from '@workos/authkit-tanstack-react-start';
|
|
151
|
+
|
|
152
|
+
export const Route = createFileRoute('/dashboard')({
|
|
153
|
+
loader: async () => {
|
|
154
|
+
const { user } = await getAuth();
|
|
155
|
+
if (!user) {
|
|
156
|
+
const signInUrl = await getSignInUrl();
|
|
157
|
+
throw redirect({ href: signInUrl });
|
|
158
|
+
}
|
|
159
|
+
return { user };
|
|
160
|
+
},
|
|
161
|
+
component: Dashboard,
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Sign Out Route
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { createFileRoute, redirect } from '@tanstack/react-router';
|
|
169
|
+
import { signOut } from '@workos/authkit-tanstack-react-start';
|
|
170
|
+
|
|
171
|
+
export const Route = createFileRoute('/signout')({
|
|
172
|
+
loader: async () => {
|
|
173
|
+
await signOut();
|
|
174
|
+
throw redirect({ href: '/' });
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Client-Side Hooks (Optional)
|
|
180
|
+
|
|
181
|
+
Only needed if you want reactive auth state in components.
|
|
182
|
+
|
|
183
|
+
**1. Add AuthKitProvider to root:**
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// src/routes/__root.tsx
|
|
187
|
+
import { AuthKitProvider } from '@workos/authkit-tanstack-react-start/client';
|
|
188
|
+
|
|
189
|
+
function RootComponent() {
|
|
190
|
+
return (
|
|
191
|
+
<AuthKitProvider>
|
|
192
|
+
<Outlet />
|
|
193
|
+
</AuthKitProvider>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**2. Use hooks in components:**
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { useAuth } from '@workos/authkit-tanstack-react-start/client';
|
|
202
|
+
|
|
203
|
+
function Profile() {
|
|
204
|
+
const { user, isLoading } = useAuth();
|
|
205
|
+
// ...
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Note:** Server-side `getAuth()` is preferred for most use cases.
|
|
78
210
|
|
|
79
211
|
## Error Recovery
|
|
80
212
|
|
|
81
213
|
### "AuthKit middleware is not configured"
|
|
82
214
|
|
|
83
|
-
**Cause:** `authkitMiddleware()` not
|
|
84
|
-
**Fix:**
|
|
85
|
-
**Verify:** `grep "authkitMiddleware"
|
|
215
|
+
**Cause:** `authkitMiddleware()` not in start.ts
|
|
216
|
+
**Fix:** Create/update `src/start.ts` with middleware config
|
|
217
|
+
**Verify:** `grep -r "authkitMiddleware" src/`
|
|
86
218
|
|
|
87
219
|
### "Module not found" for SDK
|
|
88
220
|
|
|
89
221
|
**Cause:** Wrong package name or not installed
|
|
90
|
-
**Fix:**
|
|
91
|
-
**Verify:** `ls node_modules
|
|
222
|
+
**Fix:** `pnpm add @workos/authkit-tanstack-react-start`
|
|
223
|
+
**Verify:** `ls node_modules/@workos/authkit-tanstack-react-start`
|
|
92
224
|
|
|
93
225
|
### Callback 404
|
|
94
226
|
|
|
95
|
-
**Cause:** Route path doesn't match WORKOS_REDIRECT_URI
|
|
96
|
-
**Fix:**
|
|
227
|
+
**Cause:** Route file path doesn't match WORKOS_REDIRECT_URI
|
|
228
|
+
**Fix:**
|
|
229
|
+
|
|
230
|
+
- URI `/api/auth/callback` → file `src/routes/api.auth.callback.tsx` (flat) or `app/routes/api/auth/callback.tsx` (nested)
|
|
231
|
+
- Route path string in `createFileRoute()` must match exactly
|
|
97
232
|
|
|
98
|
-
### getAuth returns undefined
|
|
233
|
+
### getAuth returns undefined user
|
|
99
234
|
|
|
100
|
-
**Cause:** Middleware not configured
|
|
101
|
-
**Fix:**
|
|
235
|
+
**Cause:** Middleware not configured or not running
|
|
236
|
+
**Fix:** Ensure `authkitMiddleware()` is in start.ts requestMiddleware array
|
|
102
237
|
|
|
103
238
|
### "Cookie password too short"
|
|
104
239
|
|
|
105
240
|
**Cause:** WORKOS_COOKIE_PASSWORD < 32 chars
|
|
106
241
|
**Fix:** `openssl rand -base64 32`, update .env
|
|
242
|
+
|
|
243
|
+
### Build fails with route type errors
|
|
244
|
+
|
|
245
|
+
**Cause:** Route tree not regenerated after adding routes
|
|
246
|
+
**Fix:** `pnpm dev` to regenerate `routeTree.gen.ts`
|
|
247
|
+
|
|
248
|
+
## SDK Exports Reference
|
|
249
|
+
|
|
250
|
+
**Server (main export):**
|
|
251
|
+
|
|
252
|
+
- `authkitMiddleware()` - Request middleware
|
|
253
|
+
- `handleCallbackRoute()` - OAuth callback handler
|
|
254
|
+
- `getAuth()` - Get current session
|
|
255
|
+
- `signOut()` - Sign out user
|
|
256
|
+
- `getSignInUrl()` / `getSignUpUrl()` - Auth URLs
|
|
257
|
+
- `switchToOrganization()` - Change org context
|
|
258
|
+
|
|
259
|
+
**Client (`/client` subpath):**
|
|
260
|
+
|
|
261
|
+
- `AuthKitProvider` - Context provider
|
|
262
|
+
- `useAuth()` - Auth state hook
|
|
263
|
+
- `useAccessToken()` - Token management
|