@vistagenic/vista 0.2.16 → 0.3.2
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/bin/vista.js +184 -177
- package/dist/ai/agent.d.ts +37 -0
- package/dist/ai/agent.js +385 -0
- package/dist/ai/embeddings.d.ts +11 -0
- package/dist/ai/embeddings.js +71 -0
- package/dist/ai/index.d.ts +10 -0
- package/dist/ai/index.js +26 -0
- package/dist/ai/memory.d.ts +16 -0
- package/dist/ai/memory.js +39 -0
- package/dist/ai/observability.d.ts +21 -0
- package/dist/ai/observability.js +69 -0
- package/dist/ai/providers/anthropic.d.ts +2 -0
- package/dist/ai/providers/anthropic.js +190 -0
- package/dist/ai/providers/base.d.ts +7 -0
- package/dist/ai/providers/base.js +85 -0
- package/dist/ai/providers/gemini.d.ts +2 -0
- package/dist/ai/providers/gemini.js +194 -0
- package/dist/ai/providers/index.d.ts +5 -0
- package/dist/ai/providers/index.js +21 -0
- package/dist/ai/providers/mock.d.ts +8 -0
- package/dist/ai/providers/mock.js +77 -0
- package/dist/ai/providers/openai.d.ts +2 -0
- package/dist/ai/providers/openai.js +211 -0
- package/dist/ai/rag.d.ts +35 -0
- package/dist/ai/rag.js +110 -0
- package/dist/ai/react/index.d.ts +1 -0
- package/dist/ai/react/index.js +17 -0
- package/dist/ai/react/react-server.d.ts +1 -0
- package/dist/ai/react/react-server.js +17 -0
- package/dist/ai/react/use-agent.d.ts +23 -0
- package/dist/ai/react/use-agent.js +138 -0
- package/dist/ai/stream.d.ts +24 -0
- package/dist/ai/stream.js +109 -0
- package/dist/ai/tool.d.ts +11 -0
- package/dist/ai/tool.js +47 -0
- package/dist/ai/types.d.ts +117 -0
- package/dist/ai/types.js +5 -0
- package/dist/auth/core.d.ts +140 -0
- package/dist/auth/core.js +165 -0
- package/dist/auth/index.d.ts +20 -8
- package/dist/auth/index.js +369 -16
- package/dist/auth/react-server.d.ts +1 -0
- package/dist/auth/react-server.js +10 -0
- package/dist/auth/react.d.ts +18 -0
- package/dist/auth/react.js +71 -0
- package/dist/bin/build-rsc.js +602 -604
- package/dist/bin/build.js +389 -388
- package/dist/bin/deploy-output.d.ts +2 -7
- package/dist/bin/deploy-output.js +3 -76
- package/dist/bin/deploy.d.ts +7 -0
- package/dist/bin/deploy.js +102 -0
- package/dist/bin/dev-error-overlay-snippet.js +778 -552
- package/dist/bin/devtools-indicator-snippet.js +387 -387
- package/dist/bin/generate.js +510 -248
- package/dist/build/manifest.d.ts +169 -139
- package/dist/build/manifest.js +423 -367
- package/dist/build/rsc/client-manifest.d.ts +62 -52
- package/dist/build/rsc/client-manifest.js +295 -193
- package/dist/build/rsc/client-reference-plugin.d.ts +37 -37
- package/dist/build/rsc/client-reference-plugin.js +160 -160
- package/dist/build/rsc/native-scanner.d.ts +135 -123
- package/dist/build/rsc/native-scanner.js +203 -170
- package/dist/build/rsc/react-client-reference-manifest.d.ts +28 -22
- package/dist/build/rsc/react-client-reference-manifest.js +240 -219
- package/dist/build/rsc/rsc-renderer.d.ts +99 -99
- package/dist/build/rsc/rsc-renderer.js +263 -263
- package/dist/build/rsc/server-component-loader.d.ts +19 -19
- package/dist/build/rsc/server-component-loader.js +91 -91
- package/dist/build/rsc/server-manifest.d.ts +17 -0
- package/dist/build/rsc/server-manifest.js +20 -0
- package/dist/build/standalone.js +337 -334
- package/dist/build/webpack/plugins/vista-flight-plugin.js +5 -5
- package/dist/client/dynamic.react-server.d.ts +2 -0
- package/dist/client/dynamic.react-server.js +23 -0
- package/dist/client/link.react-server.d.ts +2 -0
- package/dist/client/link.react-server.js +11 -0
- package/dist/client/navigation.react-server.d.ts +1 -0
- package/dist/client/navigation.react-server.js +17 -0
- package/dist/client/router.react-server.d.ts +1 -0
- package/dist/client/router.react-server.js +17 -0
- package/dist/client/rsc-router.react-server.d.ts +1 -0
- package/dist/client/rsc-router.react-server.js +17 -0
- package/dist/client/script.react-server.d.ts +2 -0
- package/dist/client/script.react-server.js +23 -0
- package/dist/components/client-island.d.ts +34 -34
- package/dist/components/client-island.js +75 -75
- package/dist/config.d.ts +17 -0
- package/dist/config.js +60 -1
- package/dist/deploy/adapters/cloudflare.d.ts +2 -0
- package/dist/deploy/adapters/cloudflare.js +124 -0
- package/dist/deploy/adapters/docker.d.ts +2 -0
- package/dist/deploy/adapters/docker.js +112 -0
- package/dist/deploy/adapters/index.d.ts +15 -0
- package/dist/deploy/adapters/index.js +24 -0
- package/dist/deploy/adapters/netlify.d.ts +2 -0
- package/dist/deploy/adapters/netlify.js +115 -0
- package/dist/deploy/adapters/render.d.ts +2 -0
- package/dist/deploy/adapters/render.js +95 -0
- package/dist/deploy/adapters/vercel.d.ts +7 -0
- package/dist/deploy/adapters/vercel.js +164 -0
- package/dist/deploy/cli-runner.d.ts +8 -0
- package/dist/deploy/cli-runner.js +58 -0
- package/dist/deploy/detect.d.ts +6 -0
- package/dist/deploy/detect.js +77 -0
- package/dist/deploy/index.d.ts +24 -0
- package/dist/deploy/index.js +112 -0
- package/dist/deploy/preflight.d.ts +8 -0
- package/dist/deploy/preflight.js +80 -0
- package/dist/deploy/types.d.ts +48 -0
- package/dist/deploy/types.js +2 -0
- package/dist/deploy/utils.d.ts +18 -0
- package/dist/deploy/utils.js +70 -0
- package/dist/dev-error.d.ts +14 -0
- package/dist/dev-error.js +1763 -705
- package/dist/index.d.ts +23 -21
- package/dist/index.js +61 -57
- package/dist/server/cookie-parse.d.ts +4 -0
- package/dist/server/cookie-parse.js +14 -0
- package/dist/server/engine.js +7 -26
- package/dist/server/index.d.ts +109 -102
- package/dist/server/index.js +315 -286
- package/dist/server/middleware-runner.d.ts +125 -57
- package/dist/server/middleware-runner.js +615 -218
- package/dist/server/middleware-security.d.ts +36 -0
- package/dist/server/middleware-security.js +183 -0
- package/dist/server/module-compile-hook.js +695 -662
- package/dist/server/route-handler-registry.d.ts +65 -0
- package/dist/server/route-handler-registry.js +195 -0
- package/dist/server/route-patterns.d.ts +67 -0
- package/dist/server/route-patterns.js +186 -0
- package/dist/server/rsc-engine.js +75 -92
- package/dist/server/rsc-module-system.d.ts +33 -33
- package/dist/server/rsc-module-system.js +87 -87
- package/dist/server/rsc-upstream.js +892 -888
- package/dist/server/static-generator.js +10 -10
- package/dist/server/typed-api-runtime.d.ts +18 -0
- package/dist/server/typed-api-runtime.js +635 -507
- package/dist/server/vista-import-map.js +134 -123
- package/dist/stack/index.d.ts +34 -32
- package/dist/stack/index.js +49 -45
- package/dist/stack/server/caller.d.ts +13 -0
- package/dist/stack/server/caller.js +42 -0
- package/dist/stack/server/executor.d.ts +40 -36
- package/dist/stack/server/executor.js +222 -174
- package/dist/stack/server/index.d.ts +11 -10
- package/dist/stack/server/index.js +24 -23
- package/dist/stack/server/procedure.d.ts +20 -18
- package/dist/stack/server/procedure.js +66 -58
- package/dist/stack/server/types.d.ts +113 -100
- package/dist/theme/react-server.d.ts +10 -0
- package/dist/theme/react-server.js +16 -0
- package/package.json +28 -3
- package/LICENSE +0 -21
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentStream = void 0;
|
|
4
|
+
exports.createAIStreamResponse = createAIStreamResponse;
|
|
5
|
+
class AgentStream {
|
|
6
|
+
source;
|
|
7
|
+
constructor(source) {
|
|
8
|
+
this.source = source;
|
|
9
|
+
}
|
|
10
|
+
[Symbol.asyncIterator]() {
|
|
11
|
+
return this.source[Symbol.asyncIterator]();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Converts the stream into a Server-Sent Events (SSE) Response.
|
|
15
|
+
* Format is compatible with UI clients and standard EventSource.
|
|
16
|
+
*/
|
|
17
|
+
toDataStreamResponse(init) {
|
|
18
|
+
const encoder = new TextEncoder();
|
|
19
|
+
const source = this.source;
|
|
20
|
+
const stream = new ReadableStream({
|
|
21
|
+
async start(controller) {
|
|
22
|
+
try {
|
|
23
|
+
for await (const chunk of source) {
|
|
24
|
+
const line = `data: ${JSON.stringify(chunk)}\n\n`;
|
|
25
|
+
controller.enqueue(encoder.encode(line));
|
|
26
|
+
}
|
|
27
|
+
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
|
|
28
|
+
controller.close();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const errChunk = {
|
|
32
|
+
type: 'error',
|
|
33
|
+
error: error?.message || 'Stream processing error',
|
|
34
|
+
};
|
|
35
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(errChunk)}\n\n`));
|
|
36
|
+
controller.close();
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const headers = new Headers(init?.headers);
|
|
41
|
+
headers.set('Content-Type', 'text/event-stream; charset=utf-8');
|
|
42
|
+
headers.set('Cache-Control', 'no-cache, no-transform');
|
|
43
|
+
headers.set('Connection', 'keep-alive');
|
|
44
|
+
return new Response(stream, {
|
|
45
|
+
...init,
|
|
46
|
+
status: init?.status ?? 200,
|
|
47
|
+
headers,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Converts the stream into a simple text-only Response stream.
|
|
52
|
+
*/
|
|
53
|
+
toTextStreamResponse(init) {
|
|
54
|
+
const encoder = new TextEncoder();
|
|
55
|
+
const source = this.source;
|
|
56
|
+
const stream = new ReadableStream({
|
|
57
|
+
async start(controller) {
|
|
58
|
+
try {
|
|
59
|
+
for await (const chunk of source) {
|
|
60
|
+
if (chunk.type === 'text-delta' && chunk.textDelta) {
|
|
61
|
+
controller.enqueue(encoder.encode(chunk.textDelta));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
controller.close();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
controller.error(error);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
const headers = new Headers(init?.headers);
|
|
72
|
+
if (!headers.has('Content-Type')) {
|
|
73
|
+
headers.set('Content-Type', 'text/plain; charset=utf-8');
|
|
74
|
+
}
|
|
75
|
+
headers.set('Cache-Control', 'no-cache');
|
|
76
|
+
return new Response(stream, {
|
|
77
|
+
...init,
|
|
78
|
+
status: init?.status ?? 200,
|
|
79
|
+
headers,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Collects all text and events from the stream into a single result.
|
|
84
|
+
*/
|
|
85
|
+
async collect() {
|
|
86
|
+
let text = '';
|
|
87
|
+
const toolCalls = [];
|
|
88
|
+
let usage;
|
|
89
|
+
for await (const chunk of this.source) {
|
|
90
|
+
if (chunk.type === 'text-delta' && chunk.textDelta) {
|
|
91
|
+
text += chunk.textDelta;
|
|
92
|
+
}
|
|
93
|
+
else if (chunk.type === 'tool-call' && chunk.toolCall) {
|
|
94
|
+
toolCalls.push(chunk.toolCall);
|
|
95
|
+
}
|
|
96
|
+
else if (chunk.type === 'done' && chunk.usage) {
|
|
97
|
+
usage = chunk.usage;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { text, toolCalls, usage };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.AgentStream = AgentStream;
|
|
104
|
+
function createAIStreamResponse(stream, init) {
|
|
105
|
+
if (stream instanceof AgentStream) {
|
|
106
|
+
return stream.toDataStreamResponse(init);
|
|
107
|
+
}
|
|
108
|
+
return new AgentStream(stream).toDataStreamResponse(init);
|
|
109
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolDefinition, ToolContext } from './types';
|
|
2
|
+
export interface ToolOptions<TParams = any, TResult = any> {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
parameters?: any;
|
|
6
|
+
execute: (args: TParams, context?: ToolContext) => Promise<TResult> | TResult;
|
|
7
|
+
}
|
|
8
|
+
export declare function tool<TParams = any, TResult = any>(options: ToolOptions<TParams, TResult>): ToolDefinition<TParams, TResult>;
|
|
9
|
+
export declare function formatToolForOpenAI(tool: ToolDefinition): any;
|
|
10
|
+
export declare function formatToolForAnthropic(tool: ToolDefinition): any;
|
|
11
|
+
export declare function formatToolForGemini(tool: ToolDefinition): any;
|
package/dist/ai/tool.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tool = tool;
|
|
4
|
+
exports.formatToolForOpenAI = formatToolForOpenAI;
|
|
5
|
+
exports.formatToolForAnthropic = formatToolForAnthropic;
|
|
6
|
+
exports.formatToolForGemini = formatToolForGemini;
|
|
7
|
+
function tool(options) {
|
|
8
|
+
if (!options.name || typeof options.name !== 'string') {
|
|
9
|
+
throw new Error('Tool must have a valid string name');
|
|
10
|
+
}
|
|
11
|
+
if (!options.description || typeof options.description !== 'string') {
|
|
12
|
+
throw new Error(`Tool "${options.name}" must have a description`);
|
|
13
|
+
}
|
|
14
|
+
if (typeof options.execute !== 'function') {
|
|
15
|
+
throw new Error(`Tool "${options.name}" must have an execute function`);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
name: options.name,
|
|
19
|
+
description: options.description,
|
|
20
|
+
parameters: options.parameters || { type: 'object', properties: {} },
|
|
21
|
+
execute: options.execute,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function formatToolForOpenAI(tool) {
|
|
25
|
+
return {
|
|
26
|
+
type: 'function',
|
|
27
|
+
function: {
|
|
28
|
+
name: tool.name,
|
|
29
|
+
description: tool.description,
|
|
30
|
+
parameters: tool.parameters || { type: 'object', properties: {} },
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function formatToolForAnthropic(tool) {
|
|
35
|
+
return {
|
|
36
|
+
name: tool.name,
|
|
37
|
+
description: tool.description,
|
|
38
|
+
input_schema: tool.parameters || { type: 'object', properties: {} },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function formatToolForGemini(tool) {
|
|
42
|
+
return {
|
|
43
|
+
name: tool.name,
|
|
44
|
+
description: tool.description,
|
|
45
|
+
parameters: tool.parameters || { type: 'object', properties: {} },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vista AI Core Types
|
|
3
|
+
*/
|
|
4
|
+
export type Role = 'system' | 'user' | 'assistant' | 'tool';
|
|
5
|
+
export interface ToolCall {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
arguments: Record<string, any> | string;
|
|
9
|
+
}
|
|
10
|
+
export interface ToolResult {
|
|
11
|
+
toolCallId: string;
|
|
12
|
+
name: string;
|
|
13
|
+
result: any;
|
|
14
|
+
isError?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface Message {
|
|
17
|
+
role: Role;
|
|
18
|
+
content: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
toolCallId?: string;
|
|
21
|
+
toolCalls?: ToolCall[];
|
|
22
|
+
}
|
|
23
|
+
export interface TokenUsage {
|
|
24
|
+
promptTokens: number;
|
|
25
|
+
completionTokens: number;
|
|
26
|
+
totalTokens: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ModelOptions {
|
|
29
|
+
model: string;
|
|
30
|
+
apiKey?: string;
|
|
31
|
+
baseURL?: string;
|
|
32
|
+
temperature?: number;
|
|
33
|
+
maxTokens?: number;
|
|
34
|
+
topP?: number;
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
export interface GenerateTextOptions {
|
|
38
|
+
messages: Message[];
|
|
39
|
+
systemPrompt?: string;
|
|
40
|
+
tools?: ToolDefinition[];
|
|
41
|
+
temperature?: number;
|
|
42
|
+
maxTokens?: number;
|
|
43
|
+
abortSignal?: AbortSignal;
|
|
44
|
+
}
|
|
45
|
+
export interface GenerateTextResult {
|
|
46
|
+
text: string;
|
|
47
|
+
toolCalls?: ToolCall[];
|
|
48
|
+
usage?: TokenUsage;
|
|
49
|
+
finishReason?: 'stop' | 'tool-calls' | 'length' | 'error' | string;
|
|
50
|
+
raw?: any;
|
|
51
|
+
}
|
|
52
|
+
export type StreamChunkType = 'text-delta' | 'tool-call' | 'tool-result' | 'step-finish' | 'error' | 'done';
|
|
53
|
+
export interface StreamChunk {
|
|
54
|
+
type: StreamChunkType;
|
|
55
|
+
textDelta?: string;
|
|
56
|
+
toolCall?: ToolCall;
|
|
57
|
+
toolResult?: ToolResult;
|
|
58
|
+
usage?: TokenUsage;
|
|
59
|
+
error?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface LanguageModel {
|
|
62
|
+
provider: string;
|
|
63
|
+
modelName: string;
|
|
64
|
+
generateText(options: GenerateTextOptions): Promise<GenerateTextResult>;
|
|
65
|
+
streamText(options: GenerateTextOptions): AsyncIterable<StreamChunk>;
|
|
66
|
+
}
|
|
67
|
+
export interface ToolContext {
|
|
68
|
+
step: number;
|
|
69
|
+
messages: Message[];
|
|
70
|
+
agentName?: string;
|
|
71
|
+
abortSignal?: AbortSignal;
|
|
72
|
+
}
|
|
73
|
+
export interface ToolDefinition<TParams = any, TResult = any> {
|
|
74
|
+
name: string;
|
|
75
|
+
description: string;
|
|
76
|
+
parameters?: any;
|
|
77
|
+
execute: (args: TParams, context?: ToolContext) => Promise<TResult> | TResult;
|
|
78
|
+
}
|
|
79
|
+
export interface AgentStep {
|
|
80
|
+
stepNumber: number;
|
|
81
|
+
prompt: Message[];
|
|
82
|
+
text: string;
|
|
83
|
+
toolCalls?: ToolCall[];
|
|
84
|
+
toolResults?: ToolResult[];
|
|
85
|
+
usage?: TokenUsage;
|
|
86
|
+
}
|
|
87
|
+
export interface AgentExecutionResult {
|
|
88
|
+
text: string;
|
|
89
|
+
messages: Message[];
|
|
90
|
+
steps: AgentStep[];
|
|
91
|
+
usage: TokenUsage;
|
|
92
|
+
finishReason: string;
|
|
93
|
+
}
|
|
94
|
+
export interface ObservabilityHandler {
|
|
95
|
+
onStepStart?: (stepNumber: number) => void;
|
|
96
|
+
onStepFinish?: (step: AgentStep) => void;
|
|
97
|
+
onToolCall?: (call: ToolCall) => void;
|
|
98
|
+
onToolResult?: (result: ToolResult) => void;
|
|
99
|
+
onError?: (error: Error) => void;
|
|
100
|
+
}
|
|
101
|
+
export interface AgentMemory {
|
|
102
|
+
get(sessionId: string): Promise<Message[]> | Message[];
|
|
103
|
+
save(sessionId: string, messages: Message[]): Promise<void> | void;
|
|
104
|
+
clear(sessionId: string): Promise<void> | void;
|
|
105
|
+
}
|
|
106
|
+
export interface AgentConfig {
|
|
107
|
+
name: string;
|
|
108
|
+
model: string | LanguageModel;
|
|
109
|
+
systemPrompt?: string | (() => string | Promise<string>);
|
|
110
|
+
tools?: (ToolDefinition | any)[];
|
|
111
|
+
memory?: boolean | AgentMemory;
|
|
112
|
+
maxSteps?: number;
|
|
113
|
+
temperature?: number;
|
|
114
|
+
maxTokens?: number;
|
|
115
|
+
observability?: boolean | ObservabilityHandler;
|
|
116
|
+
onStepFinish?: (step: AgentStep) => void | Promise<void>;
|
|
117
|
+
}
|
package/dist/ai/types.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export interface AuthUser {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string | null;
|
|
4
|
+
email?: string | null;
|
|
5
|
+
image?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthSession {
|
|
8
|
+
user: AuthUser;
|
|
9
|
+
expires: string;
|
|
10
|
+
}
|
|
11
|
+
export interface JWTPayload extends AuthSession {
|
|
12
|
+
iat: number;
|
|
13
|
+
exp: number;
|
|
14
|
+
}
|
|
15
|
+
export interface Account {
|
|
16
|
+
provider: string;
|
|
17
|
+
type: 'oauth' | 'oidc' | 'credentials';
|
|
18
|
+
providerAccountId: string;
|
|
19
|
+
access_token?: string;
|
|
20
|
+
refresh_token?: string;
|
|
21
|
+
token_type?: string;
|
|
22
|
+
scope?: string;
|
|
23
|
+
id_token?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Adapter {
|
|
26
|
+
createUser?(user: AuthUser): Promise<AuthUser> | AuthUser;
|
|
27
|
+
getUser?(id: string): Promise<AuthUser | null> | AuthUser | null;
|
|
28
|
+
getUserByEmail?(email: string): Promise<AuthUser | null> | AuthUser | null;
|
|
29
|
+
getUserByAccount?(provider: string, providerAccountId: string): Promise<AuthUser | null> | AuthUser | null;
|
|
30
|
+
linkAccount?(userId: string, account: Account): Promise<void> | void;
|
|
31
|
+
}
|
|
32
|
+
export interface OAuthProvider {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: 'oauth';
|
|
36
|
+
clientId: string;
|
|
37
|
+
clientSecret: string;
|
|
38
|
+
authorization: {
|
|
39
|
+
url: string;
|
|
40
|
+
params?: Record<string, string>;
|
|
41
|
+
};
|
|
42
|
+
token: string;
|
|
43
|
+
userinfo: string;
|
|
44
|
+
profile(profile: any): AuthUser | Promise<AuthUser>;
|
|
45
|
+
}
|
|
46
|
+
export interface CredentialsProvider {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
type: 'credentials';
|
|
50
|
+
credentials: Record<string, {
|
|
51
|
+
label?: string;
|
|
52
|
+
type?: string;
|
|
53
|
+
}>;
|
|
54
|
+
authorize(credentials: Record<string, string>): Promise<AuthUser | null> | AuthUser | null;
|
|
55
|
+
}
|
|
56
|
+
export type AuthProvider = OAuthProvider | CredentialsProvider;
|
|
57
|
+
export interface AuthCallbacks {
|
|
58
|
+
signIn?: (params: {
|
|
59
|
+
user: AuthUser;
|
|
60
|
+
account?: Account | null;
|
|
61
|
+
}) => boolean | Promise<boolean>;
|
|
62
|
+
jwt?: (params: {
|
|
63
|
+
token: JWTPayload;
|
|
64
|
+
user?: AuthUser;
|
|
65
|
+
}) => JWTPayload | Promise<JWTPayload>;
|
|
66
|
+
session?: (params: {
|
|
67
|
+
session: AuthSession;
|
|
68
|
+
token: JWTPayload;
|
|
69
|
+
}) => AuthSession | Promise<AuthSession>;
|
|
70
|
+
redirect?: (params: {
|
|
71
|
+
url: string;
|
|
72
|
+
baseUrl: string;
|
|
73
|
+
}) => string | Promise<string>;
|
|
74
|
+
authorized?: (params: {
|
|
75
|
+
auth: AuthSession | null;
|
|
76
|
+
request: Request;
|
|
77
|
+
}) => boolean | Response | Promise<boolean | Response>;
|
|
78
|
+
}
|
|
79
|
+
export interface AuthConfig {
|
|
80
|
+
providers: AuthProvider[];
|
|
81
|
+
adapter?: Adapter;
|
|
82
|
+
secret?: string;
|
|
83
|
+
session?: {
|
|
84
|
+
strategy?: 'jwt' | 'database';
|
|
85
|
+
maxAge?: number;
|
|
86
|
+
cookieName?: string;
|
|
87
|
+
};
|
|
88
|
+
pages?: {
|
|
89
|
+
signIn?: string;
|
|
90
|
+
error?: string;
|
|
91
|
+
};
|
|
92
|
+
callbacks?: AuthCallbacks;
|
|
93
|
+
trustHost?: boolean;
|
|
94
|
+
basePath?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface ResolvedAuthConfig extends AuthConfig {
|
|
97
|
+
secret: string;
|
|
98
|
+
session: {
|
|
99
|
+
strategy: 'jwt' | 'database';
|
|
100
|
+
maxAge: number;
|
|
101
|
+
cookieName: string;
|
|
102
|
+
};
|
|
103
|
+
basePath: string;
|
|
104
|
+
}
|
|
105
|
+
export declare function hashPassword(password: string, salt?: string): string;
|
|
106
|
+
export declare function verifyPassword(password: string, stored: string): boolean;
|
|
107
|
+
export declare function randomToken(bytes?: number): string;
|
|
108
|
+
export declare function encryptJwt(payload: JWTPayload, secret: string): string;
|
|
109
|
+
export declare function decryptJwt(token: string, secret: string): JWTPayload | null;
|
|
110
|
+
export declare function pkcePair(): {
|
|
111
|
+
verifier: string;
|
|
112
|
+
challenge: string;
|
|
113
|
+
};
|
|
114
|
+
export declare class MemoryAdapter implements Adapter {
|
|
115
|
+
users: Map<string, AuthUser>;
|
|
116
|
+
accounts: Map<string, string>;
|
|
117
|
+
createUser(user: AuthUser): AuthUser;
|
|
118
|
+
getUser(id: string): AuthUser | null;
|
|
119
|
+
getUserByEmail(email: string): AuthUser | null;
|
|
120
|
+
getUserByAccount(provider: string, providerAccountId: string): AuthUser | null;
|
|
121
|
+
linkAccount(userId: string, account: Account): void;
|
|
122
|
+
}
|
|
123
|
+
export declare function GitHub(options: {
|
|
124
|
+
clientId?: string;
|
|
125
|
+
clientSecret?: string;
|
|
126
|
+
}): OAuthProvider;
|
|
127
|
+
export declare function Google(options?: {
|
|
128
|
+
clientId?: string;
|
|
129
|
+
clientSecret?: string;
|
|
130
|
+
}): OAuthProvider;
|
|
131
|
+
export declare function Credentials(options: {
|
|
132
|
+
id?: string;
|
|
133
|
+
name?: string;
|
|
134
|
+
credentials?: Record<string, {
|
|
135
|
+
label?: string;
|
|
136
|
+
type?: string;
|
|
137
|
+
}>;
|
|
138
|
+
authorize: CredentialsProvider['authorize'];
|
|
139
|
+
}): CredentialsProvider;
|
|
140
|
+
export declare function resolveAuthConfig(config: AuthConfig): ResolvedAuthConfig;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MemoryAdapter = void 0;
|
|
7
|
+
exports.hashPassword = hashPassword;
|
|
8
|
+
exports.verifyPassword = verifyPassword;
|
|
9
|
+
exports.randomToken = randomToken;
|
|
10
|
+
exports.encryptJwt = encryptJwt;
|
|
11
|
+
exports.decryptJwt = decryptJwt;
|
|
12
|
+
exports.pkcePair = pkcePair;
|
|
13
|
+
exports.GitHub = GitHub;
|
|
14
|
+
exports.Google = Google;
|
|
15
|
+
exports.Credentials = Credentials;
|
|
16
|
+
exports.resolveAuthConfig = resolveAuthConfig;
|
|
17
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
18
|
+
function hashPassword(password, salt) {
|
|
19
|
+
const usedSalt = salt || node_crypto_1.default.randomBytes(16).toString('hex');
|
|
20
|
+
const derived = node_crypto_1.default.scryptSync(password, usedSalt, 32).toString('hex');
|
|
21
|
+
return `${usedSalt}:${derived}`;
|
|
22
|
+
}
|
|
23
|
+
function verifyPassword(password, stored) {
|
|
24
|
+
const [salt, hash] = stored.split(':');
|
|
25
|
+
if (!salt || !hash)
|
|
26
|
+
return false;
|
|
27
|
+
const derived = node_crypto_1.default.scryptSync(password, salt, 32);
|
|
28
|
+
const actual = Buffer.from(hash, 'hex');
|
|
29
|
+
if (derived.length !== actual.length)
|
|
30
|
+
return false;
|
|
31
|
+
return node_crypto_1.default.timingSafeEqual(derived, actual);
|
|
32
|
+
}
|
|
33
|
+
function randomToken(bytes = 32) {
|
|
34
|
+
return node_crypto_1.default.randomBytes(bytes).toString('base64url');
|
|
35
|
+
}
|
|
36
|
+
function deriveKey(secret) {
|
|
37
|
+
return node_crypto_1.default.createHash('sha256').update(secret).digest();
|
|
38
|
+
}
|
|
39
|
+
function encryptJwt(payload, secret) {
|
|
40
|
+
const iv = node_crypto_1.default.randomBytes(12);
|
|
41
|
+
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', deriveKey(secret), iv);
|
|
42
|
+
const encrypted = Buffer.concat([cipher.update(JSON.stringify(payload), 'utf8'), cipher.final()]);
|
|
43
|
+
const tag = cipher.getAuthTag();
|
|
44
|
+
return Buffer.concat([iv, tag, encrypted]).toString('base64url');
|
|
45
|
+
}
|
|
46
|
+
function decryptJwt(token, secret) {
|
|
47
|
+
try {
|
|
48
|
+
const buffer = Buffer.from(token, 'base64url');
|
|
49
|
+
const iv = buffer.subarray(0, 12);
|
|
50
|
+
const tag = buffer.subarray(12, 28);
|
|
51
|
+
const encrypted = buffer.subarray(28);
|
|
52
|
+
const decipher = node_crypto_1.default.createDecipheriv('aes-256-gcm', deriveKey(secret), iv);
|
|
53
|
+
decipher.setAuthTag(tag);
|
|
54
|
+
const json = Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
|
|
55
|
+
const payload = JSON.parse(json);
|
|
56
|
+
if (payload.exp * 1000 < Date.now()) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return payload;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function pkcePair() {
|
|
66
|
+
const verifier = randomToken(32);
|
|
67
|
+
const challenge = node_crypto_1.default.createHash('sha256').update(verifier).digest('base64url');
|
|
68
|
+
return { verifier, challenge };
|
|
69
|
+
}
|
|
70
|
+
class MemoryAdapter {
|
|
71
|
+
users = new Map();
|
|
72
|
+
accounts = new Map();
|
|
73
|
+
createUser(user) {
|
|
74
|
+
this.users.set(user.id, user);
|
|
75
|
+
return user;
|
|
76
|
+
}
|
|
77
|
+
getUser(id) {
|
|
78
|
+
return this.users.get(id) ?? null;
|
|
79
|
+
}
|
|
80
|
+
getUserByEmail(email) {
|
|
81
|
+
return Array.from(this.users.values()).find((user) => user.email === email) ?? null;
|
|
82
|
+
}
|
|
83
|
+
getUserByAccount(provider, providerAccountId) {
|
|
84
|
+
const userId = this.accounts.get(`${provider}:${providerAccountId}`);
|
|
85
|
+
return userId ? this.getUser(userId) : null;
|
|
86
|
+
}
|
|
87
|
+
linkAccount(userId, account) {
|
|
88
|
+
this.accounts.set(`${account.provider}:${account.providerAccountId}`, userId);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.MemoryAdapter = MemoryAdapter;
|
|
92
|
+
function GitHub(options) {
|
|
93
|
+
return {
|
|
94
|
+
id: 'github',
|
|
95
|
+
name: 'GitHub',
|
|
96
|
+
type: 'oauth',
|
|
97
|
+
clientId: options.clientId || process.env.AUTH_GITHUB_ID || process.env.GITHUB_ID || '',
|
|
98
|
+
clientSecret: options.clientSecret || process.env.AUTH_GITHUB_SECRET || process.env.GITHUB_SECRET || '',
|
|
99
|
+
authorization: {
|
|
100
|
+
url: 'https://github.com/login/oauth/authorize',
|
|
101
|
+
params: { scope: 'read:user user:email' },
|
|
102
|
+
},
|
|
103
|
+
token: 'https://github.com/login/oauth/access_token',
|
|
104
|
+
userinfo: 'https://api.github.com/user',
|
|
105
|
+
profile(profile) {
|
|
106
|
+
return {
|
|
107
|
+
id: String(profile.id),
|
|
108
|
+
name: profile.name || profile.login,
|
|
109
|
+
email: profile.email,
|
|
110
|
+
image: profile.avatar_url,
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function Google(options = {}) {
|
|
116
|
+
return {
|
|
117
|
+
id: 'google',
|
|
118
|
+
name: 'Google',
|
|
119
|
+
type: 'oauth',
|
|
120
|
+
clientId: options.clientId || process.env.AUTH_GOOGLE_ID || process.env.GOOGLE_ID || '',
|
|
121
|
+
clientSecret: options.clientSecret || process.env.AUTH_GOOGLE_SECRET || process.env.GOOGLE_SECRET || '',
|
|
122
|
+
authorization: {
|
|
123
|
+
url: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
124
|
+
params: { scope: 'openid email profile', response_type: 'code' },
|
|
125
|
+
},
|
|
126
|
+
token: 'https://oauth2.googleapis.com/token',
|
|
127
|
+
userinfo: 'https://openidconnect.googleapis.com/v1/userinfo',
|
|
128
|
+
profile(profile) {
|
|
129
|
+
return {
|
|
130
|
+
id: String(profile.sub || profile.id),
|
|
131
|
+
name: profile.name,
|
|
132
|
+
email: profile.email,
|
|
133
|
+
image: profile.picture,
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function Credentials(options) {
|
|
139
|
+
return {
|
|
140
|
+
id: options.id || 'credentials',
|
|
141
|
+
name: options.name || 'Credentials',
|
|
142
|
+
type: 'credentials',
|
|
143
|
+
credentials: options.credentials || {
|
|
144
|
+
email: { label: 'Email', type: 'email' },
|
|
145
|
+
password: { label: 'Password', type: 'password' },
|
|
146
|
+
},
|
|
147
|
+
authorize: options.authorize,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function resolveAuthConfig(config) {
|
|
151
|
+
const secret = config.secret || process.env.AUTH_SECRET || process.env.NEXTAUTH_SECRET;
|
|
152
|
+
if (!secret) {
|
|
153
|
+
throw new Error('AUTH_SECRET is required. Set it in the environment or pass secret to VistaAuth().');
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
...config,
|
|
157
|
+
secret,
|
|
158
|
+
basePath: config.basePath || '/api/auth',
|
|
159
|
+
session: {
|
|
160
|
+
strategy: config.session?.strategy || 'jwt',
|
|
161
|
+
maxAge: config.session?.maxAge ?? 30 * 24 * 60 * 60,
|
|
162
|
+
cookieName: config.session?.cookieName || 'vista.session-token',
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { type AuthConfig, type AuthSession, type ResolvedAuthConfig } from './core';
|
|
2
|
+
export * from './core';
|
|
3
|
+
export declare function VistaAuth(config: AuthConfig): {
|
|
4
|
+
handlers: {
|
|
5
|
+
GET: (request: Request) => Promise<Response>;
|
|
6
|
+
POST: (request: Request) => Promise<Response>;
|
|
7
|
+
};
|
|
8
|
+
auth: (request?: Request) => Promise<AuthSession | null>;
|
|
9
|
+
signIn: (providerId?: string, options?: Record<string, string>) => Promise<Response>;
|
|
10
|
+
signOut: () => Promise<Response>;
|
|
11
|
+
authMiddleware: (authorized?: (params: {
|
|
12
|
+
auth: AuthSession | null;
|
|
13
|
+
request: Request;
|
|
14
|
+
}) => boolean | Response | Promise<boolean | Response>) => ({ request, next }: {
|
|
15
|
+
request: any;
|
|
16
|
+
next: () => Promise<Response>;
|
|
17
|
+
}) => Promise<Response>;
|
|
18
|
+
config: ResolvedAuthConfig;
|
|
19
|
+
};
|
|
20
|
+
export default VistaAuth;
|