@llmnative/react 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +11 -1
  2. package/dist/index.css +3 -1
  3. package/dist/index.js +20 -23
  4. package/dist/index.mjs +18045 -16868
  5. package/dist/types/src/App.d.ts +4 -1
  6. package/dist/types/src/I18n.d.ts +4 -0
  7. package/dist/types/src/components/ErrorBoundary.d.ts +1 -1
  8. package/dist/types/src/components/blocks/Brand.d.ts +5 -0
  9. package/dist/types/src/components/blocks/Carousel.d.ts +2 -0
  10. package/dist/types/src/components/blocks/Dropdown.d.ts +39 -2
  11. package/dist/types/src/components/blocks/ListCard.d.ts +7 -0
  12. package/dist/types/src/components/blocks/Menu.d.ts +2 -0
  13. package/dist/types/src/components/blocks/Notifications.d.ts +4 -1
  14. package/dist/types/src/components/blocks/ProviderSwitcher.d.ts +3 -1
  15. package/dist/types/src/components/blocks/Search.d.ts +1 -0
  16. package/dist/types/src/components/blocks/ThemeSwitcher.d.ts +6 -2
  17. package/dist/types/src/components/blocks/Toolbar.d.ts +4 -0
  18. package/dist/types/src/components/index.d.ts +2 -2
  19. package/dist/types/src/components/ui/Alert.d.ts +5 -1
  20. package/dist/types/src/components/ui/Badge.d.ts +6 -0
  21. package/dist/types/src/components/ui/Buttons.d.ts +5 -2
  22. package/dist/types/src/components/ui/Card.d.ts +3 -0
  23. package/dist/types/src/components/ui/Code.d.ts +4 -0
  24. package/dist/types/src/components/ui/Gallery.d.ts +9 -2
  25. package/dist/types/src/components/ui/GridSystem.d.ts +4 -1
  26. package/dist/types/src/components/ui/Icon.d.ts +3 -0
  27. package/dist/types/src/components/ui/Image.d.ts +6 -0
  28. package/dist/types/src/components/ui/ImageAvatar.d.ts +3 -0
  29. package/dist/types/src/components/ui/Loader.d.ts +3 -1
  30. package/dist/types/src/components/ui/Modal.d.ts +22 -0
  31. package/dist/types/src/components/ui/Pagination.d.ts +2 -0
  32. package/dist/types/src/components/ui/Percentage.d.ts +9 -0
  33. package/dist/types/src/components/ui/Repeat.d.ts +0 -1
  34. package/dist/types/src/components/ui/Tab.d.ts +1 -1
  35. package/dist/types/src/components/ui/Table.d.ts +3 -0
  36. package/dist/types/src/components/ui/fields/CodeEditor.d.ts +9 -1
  37. package/dist/types/src/components/ui/fields/ContextMenu.d.ts +74 -1
  38. package/dist/types/src/components/ui/fields/RichText.d.ts +4 -1
  39. package/dist/types/src/components/ui/fields/Select.d.ts +2 -2
  40. package/dist/types/src/components/ui/fields/Upload.d.ts +17 -4
  41. package/dist/types/src/components/widgets/Form.d.ts +14 -3
  42. package/dist/types/src/components/widgets/Prompt.d.ts +35 -15
  43. package/dist/types/src/components/widgets/grid-core/GridCore.d.ts +1 -1
  44. package/dist/types/src/components/widgets/grid-core/GridGalleryView.d.ts +1 -1
  45. package/dist/types/src/components/widgets/grid-core/types.d.ts +79 -3
  46. package/dist/types/src/components/widgets/grid-core/useGridActions.d.ts +1 -1
  47. package/dist/types/src/index.d.ts +15 -5
  48. package/dist/types/src/libs/editorHeight.d.ts +11 -1
  49. package/dist/types/src/libs/fetch.d.ts +2 -0
  50. package/dist/types/src/providers/ProviderDescriptor.d.ts +18 -0
  51. package/dist/types/src/providers/ai/AIProvider.d.ts +54 -1
  52. package/dist/types/src/providers/ai/index.d.ts +13 -2
  53. package/dist/types/src/providers/ai/openaiCompatible.d.ts +25 -1
  54. package/dist/types/src/providers/ai/shared.d.ts +13 -4
  55. package/dist/types/src/providers/auth/AuthProvider.d.ts +8 -0
  56. package/dist/types/src/providers/auth/firebase/FirebaseAuthProvider.d.ts +23 -0
  57. package/dist/types/src/providers/auth/google/auth.d.ts +1 -1
  58. package/dist/types/src/providers/data/DataProvider.d.ts +8 -0
  59. package/dist/types/src/providers/data/firestore.d.ts +19 -1
  60. package/dist/types/src/providers/email/definitions.d.ts +3 -0
  61. package/dist/types/src/providers/firebase-init.d.ts +11 -5
  62. package/dist/types/src/providers/publish/PublishProvider.d.ts +29 -0
  63. package/dist/types/src/providers/publish/definitions.d.ts +3 -0
  64. package/dist/types/src/providers/storage/firebase.d.ts +7 -1
  65. package/dist/vite.js +1 -1
  66. package/dist/vite.mjs +62 -53
  67. package/package.json +58 -54
  68. package/scripts/cli/setup-devtools.js +8 -7
  69. package/scripts/cli/setup-project.js +23 -19
  70. package/themes/cyber.ts +8 -7
  71. package/themes/default.ts +22 -7
  72. package/themes/flat.ts +8 -7
  73. package/dist/style.css +0 -1
  74. package/dist/types/src/providers/email/google/apis/email.d.ts +0 -7
@@ -27,10 +27,63 @@ export interface AIRequestOptions {
27
27
  temperature?: number;
28
28
  attachments?: AIAttachment[];
29
29
  }
30
+ /** Definizione di un tool che il modello può scegliere di invocare — la SDK del provider
31
+ * riceve solo questa forma (JSON-serializzabile); l'implementazione vera resta lato
32
+ * chiamante (mai inviata al provider). Vedi AICompleteResult per come il modello segnala
33
+ * una richiesta di invocazione. */
34
+ export interface AIToolDefinition {
35
+ name: string;
36
+ description: string;
37
+ inputSchema: Record<string, unknown>;
38
+ }
39
+ /** Richiesta del modello di invocare un tool con questi argomenti — il chiamante esegue
40
+ * `name` localmente e rimanda il risultato come AIToolResult nel turno successivo. */
41
+ export interface AIToolCall {
42
+ id: string;
43
+ name: string;
44
+ input: Record<string, unknown>;
45
+ }
46
+ /** Esito dell'esecuzione locale di un tool, da rimandare al modello nel turno successivo. */
47
+ export interface AIToolResult {
48
+ toolCallId: string;
49
+ name: string;
50
+ output: unknown;
51
+ isError?: boolean;
52
+ }
53
+ /** Un turno della conversazione precedente a quello corrente — passato via
54
+ * `AICompleteRequest.history` per continuare una chat multi-turno (es. l'utente affina una
55
+ * richiesta AI già eseguita, o il modello ha invocato un tool e ne riceve il risultato). */
56
+ export type AIConversationTurn = {
57
+ role: 'user';
58
+ content: string;
59
+ } | {
60
+ role: 'assistant';
61
+ content?: string;
62
+ toolCalls?: AIToolCall[];
63
+ } | {
64
+ role: 'tool_result';
65
+ results: AIToolResult[];
66
+ };
30
67
  export interface AICompleteRequest extends AIRequestOptions {
31
68
  prompt: string;
32
69
  data?: PromptVariables;
70
+ /** Turni precedenti della conversazione — assente = primo turno (solo `prompt`). */
71
+ history?: AIConversationTurn[];
72
+ /** Tool che il modello può invocare a sua discrezione in questo turno. */
73
+ tools?: AIToolDefinition[];
74
+ /** Annulla la richiesta in corso (es. un bottone "interrompi" lato chiamante). */
75
+ signal?: AbortSignal;
33
76
  }
77
+ /** Esito di una chiamata completate — testo semplice, oppure una o più richieste di tool
78
+ * call (eventualmente accompagnate da testo, quando il modello commenta prima di invocare). */
79
+ export type AICompleteResult = {
80
+ type: 'text';
81
+ text: string;
82
+ } | {
83
+ type: 'tool_calls';
84
+ toolCalls: AIToolCall[];
85
+ text?: string;
86
+ };
34
87
  export interface AIKeyValidationResult {
35
88
  valid: boolean;
36
89
  /** Human-readable error from the provider API (e.g. "Incorrect API key provided"). */
@@ -45,7 +98,7 @@ export interface AIProviderAdapter extends ProviderConfigurable {
45
98
  /** URL to the provider's API key management page. */
46
99
  dashboardUrl?: string;
47
100
  getCapabilities(forceRefresh?: boolean): Promise<AIProviderCapabilities>;
48
- complete(request: AICompleteRequest): Promise<string | null>;
101
+ complete(request: AICompleteRequest): Promise<AICompleteResult | null>;
49
102
  /** Makes a live API call to verify the key is accepted. Never uses cache. */
50
103
  validateApiKey(): Promise<AIKeyValidationResult>;
51
104
  }
@@ -1,9 +1,20 @@
1
1
  import type { AIConfig } from '../../Config';
2
+ import type { ProviderDescriptor } from '../ProviderDescriptor';
2
3
  import type { AIProviderAdapter } from './AIProvider';
3
4
  import { type AIProviderDefinition } from './shared';
4
- export type { AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIProviderCapabilities, AIRequestOptions, AIAttachment } from './AIProvider';
5
+ export type { AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIProviderCapabilities, AIRequestOptions, AIAttachment, AICompleteRequest, AICompleteResult, AIConversationTurn, AIToolDefinition, AIToolCall, AIToolResult, } from './AIProvider';
5
6
  export { formatAIModelRef, parseAIModelRef } from './AIProvider';
6
- export type { AIModelCatalog } from './shared';
7
+ export type { AIModelCatalog, AIProviderDefinition } from './shared';
7
8
  export { getAIModelCatalog } from './shared';
8
9
  export declare const AI_PROVIDER_DEFINITIONS: AIProviderDefinition[];
10
+ /** Generic "connect this provider" view of an AIProviderDefinition — the shape a CMS/admin
11
+ * UI needs (label, description, credential fields, where to find them), independent of the
12
+ * runtime completion contract (discoverModels/complete) it also carries. */
13
+ export declare const toProviderDescriptor: (definition: AIProviderDefinition) => ProviderDescriptor;
14
+ export declare const AI_PROVIDER_DESCRIPTORS: ProviderDescriptor[];
15
+ /** The user-configurable "bring your own endpoint" slot — metadata-only counterpart of the
16
+ * dynamic definition getDynamicAIProviderDefinitions() builds once a baseUrl is actually
17
+ * known. Not part of AI_PROVIDER_DEFINITIONS (there's nothing to build a working adapter
18
+ * from until the user supplies that URL), but a "connect" UI still needs to offer it. */
19
+ export declare const OPENAI_COMPATIBLE_PROVIDER_DESCRIPTOR: ProviderDescriptor;
9
20
  export declare const createAIProviderRegistry: (aiConfig?: AIConfig) => Record<string, AIProviderAdapter>;
@@ -1,7 +1,9 @@
1
1
  import type { AIProviderDefinition, BuiltInAIProviderId } from './shared';
2
+ import type { AIConversationTurn, AICompleteResult, AIToolDefinition } from './AIProvider';
2
3
  type OpenAICompatibleDefinitionOptions = {
3
4
  id: BuiltInAIProviderId;
4
5
  label: string;
6
+ description: string;
5
7
  configKey: string;
6
8
  requiredConfigKeys?: string[];
7
9
  defaultModel: string;
@@ -10,8 +12,30 @@ type OpenAICompatibleDefinitionOptions = {
10
12
  modelsUrl?: string;
11
13
  chatCompletionsUrl?: string;
12
14
  dashboardUrl?: string;
15
+ credentialsHint?: string;
13
16
  /** Override the default validateApiKey when the models endpoint is public or uses a non-standard error format. */
14
17
  validateApiKey?: AIProviderDefinition['validateApiKey'];
15
18
  };
16
- export declare const createOpenAICompatibleProviderDefinition: ({ id, label, configKey, requiredConfigKeys, defaultModel, fallbackModels, baseUrl, modelsUrl, chatCompletionsUrl, dashboardUrl, validateApiKey: validateApiKeyOverride, }: OpenAICompatibleDefinitionOptions) => AIProviderDefinition;
19
+ /** Esportate per riuso da provider "chat completions"-simili ma non costruiti tramite
20
+ * createOpenAICompatibleProviderDefinition (vedi opencode.ts) — stesso wire format OpenAI,
21
+ * niente da reinventare. */
22
+ export declare function toOpenAITool(tool: AIToolDefinition): {
23
+ type: "function";
24
+ function: {
25
+ name: string;
26
+ description: string;
27
+ parameters: Record<string, unknown>;
28
+ };
29
+ };
30
+ /** Un turno assistant con tool_calls diventa `tool_calls` sul messaggio assistant; un turno
31
+ * tool_result diventa un messaggio `role: 'tool'` per ciascun risultato — stessa forma
32
+ * richiesta dall'API Chat Completions (OpenAI e compatibili) per continuare la conversazione
33
+ * dopo una tool call. */
34
+ export declare function toOpenAIMessages(turn: AIConversationTurn): Array<Record<string, unknown>>;
35
+ export declare function parseOpenAIResponse(response: {
36
+ choices?: Array<{
37
+ message?: Record<string, unknown>;
38
+ }>;
39
+ } | null): AICompleteResult | null;
40
+ export declare const createOpenAICompatibleProviderDefinition: ({ id, label, description, configKey, requiredConfigKeys, defaultModel, fallbackModels, baseUrl, modelsUrl, chatCompletionsUrl, dashboardUrl, credentialsHint, validateApiKey: validateApiKeyOverride, }: OpenAICompatibleDefinitionOptions) => AIProviderDefinition;
17
41
  export {};
@@ -1,18 +1,27 @@
1
1
  import { type ProviderConfigurationState } from '../ProviderConfiguration';
2
- import type { AICompleteRequest, AIKeyValidationResult, AIModelDescriptor, AIProviderAdapter, AIProviderCapabilities, AIRequestOptions } from './AIProvider';
2
+ import type { ProviderCredentialField } from '../ProviderDescriptor';
3
+ import type { AICompleteRequest, AICompleteResult, AIKeyValidationResult, AIModelDescriptor, AIProviderAdapter, AIProviderCapabilities, AIRequestOptions } from './AIProvider';
3
4
  export type BuiltInAIProviderId = 'openai' | 'openrouter' | 'opencode' | 'openai-compatible' | 'deepseek' | 'gemini' | 'anthropic' | 'mistral' | 'glm';
4
5
  export type AIProviderDefinition = {
5
6
  id: BuiltInAIProviderId;
6
7
  label: string;
8
+ /** One-line description shown in a "connect this provider" UI. */
9
+ description?: string;
7
10
  configKey?: string;
8
11
  requiredConfigKeys?: string[];
9
12
  defaultModel: string;
10
13
  fallbackModels: string[];
11
- /** URL to the provider's API key management page (shown in UI on validation error). */
14
+ /** URL to the provider's API key management page (shown in UI on validation error, and
15
+ * surfaced as ProviderDescriptor.credentialsUrl via toProviderDescriptor()). */
12
16
  dashboardUrl?: string;
17
+ /** Credential fields a "connect" UI should collect (defaults to a single apiKey field
18
+ * when omitted — see toProviderDescriptor() in ./index.ts). */
19
+ credentialFields?: ProviderCredentialField[];
20
+ /** Short guidance on where in the dashboard to find the credential. */
21
+ credentialsHint?: string;
13
22
  capabilities?: Omit<AIProviderCapabilities, 'models'>;
14
23
  discoverModels: (apiKey: string) => Promise<string[]>;
15
- complete: (apiKey: string, request: Required<Pick<AICompleteRequest, 'prompt' | 'model'>> & AIRequestOptions) => Promise<string | null>;
24
+ complete: (apiKey: string, request: Required<Pick<AICompleteRequest, 'prompt' | 'model'>> & AIRequestOptions & Pick<AICompleteRequest, 'history' | 'tools' | 'signal'>) => Promise<AICompleteResult | null>;
16
25
  /**
17
26
  * Per-provider auth check. When omitted, the default implementation in
18
27
  * RuntimeAIProvider calls discoverModels() live (no cache) and treats any
@@ -41,6 +50,6 @@ export declare class RuntimeAIProvider implements AIProviderAdapter {
41
50
  isConfigured(): boolean;
42
51
  getConfigurationState(): ProviderConfigurationState;
43
52
  getCapabilities(forceRefresh?: boolean): Promise<AIProviderCapabilities>;
44
- complete(request: AICompleteRequest): Promise<string | null>;
53
+ complete(request: AICompleteRequest): Promise<AICompleteResult | null>;
45
54
  validateApiKey(): Promise<AIKeyValidationResult>;
46
55
  }
@@ -19,4 +19,12 @@ export interface AuthProviderAdapter extends ProviderConfigurable {
19
19
  onAuthChange(callback: (user: UserProfile | null) => void): () => void;
20
20
  getAccessToken?(scopes?: string[]): Promise<string>;
21
21
  isAuthenticated?(): boolean;
22
+ /**
23
+ * Custom claims embedded in the current session's token (e.g. a JWT's payload),
24
+ * for providers backed by one — Firebase custom claims, a Supabase JWT, etc.
25
+ * Optional: providers with no token-claims concept (e.g. plain OAuth) omit it.
26
+ * Read-only/UI convenience — never a security boundary, the server always
27
+ * re-verifies the raw token itself rather than trusting client-read claims.
28
+ */
29
+ getIdTokenClaims?(): Promise<Record<string, unknown> | null>;
22
30
  }
@@ -1,5 +1,6 @@
1
1
  import type { AuthProviderAdapter, AuthSignInOptions, UserProfile } from '../AuthProvider';
2
2
  import type { ProviderConfigurationState } from '../../ProviderConfiguration';
3
+ import type { FirebaseConfig } from '../../../Config';
3
4
  /**
4
5
  * Firebase-specific sign-in options.
5
6
  *
@@ -14,7 +15,28 @@ export interface FirebaseSignInOptions extends AuthSignInOptions {
14
15
  password?: string;
15
16
  provider?: string;
16
17
  }
18
+ export interface FirebaseAuthProviderOptions {
19
+ /**
20
+ * Static config for this provider's own Firebase app. Omit when relying on
21
+ * another consumer (e.g. providers.firebase + FirebaseDataProvider, or the
22
+ * tenant-switching session factories in ProviderSession.tsx) to have already
23
+ * initialized the target app — matches the provider's original zero-arg behavior.
24
+ */
25
+ config?: FirebaseConfig;
26
+ /**
27
+ * Firebase app name this provider's session lives under. Defaults to the SDK's
28
+ * unnamed default app. Give this a dedicated name (e.g. 'control-plane') when a
29
+ * long-lived login session must coexist with the default app used by tenant
30
+ * switching — ProviderSession's 'data'/'storage' firebase factories reinitialize
31
+ * the default app on every switch, which would otherwise tear down this session.
32
+ */
33
+ appName?: string;
34
+ }
17
35
  export declare class FirebaseAuthProvider implements AuthProviderAdapter {
36
+ private readonly options;
37
+ private readonly appName?;
38
+ private readonly initPromise;
39
+ constructor(options?: FirebaseAuthProviderOptions);
18
40
  getConfigurationState(): ProviderConfigurationState;
19
41
  isConfigured(): boolean;
20
42
  getUser(): UserProfile | null;
@@ -23,4 +45,5 @@ export declare class FirebaseAuthProvider implements AuthProviderAdapter {
23
45
  signOut(): Promise<void>;
24
46
  onAuthChange(callback: (user: UserProfile | null) => void): () => void;
25
47
  getAccessToken(): Promise<string>;
48
+ getIdTokenClaims(): Promise<Record<string, unknown> | null>;
26
49
  }
@@ -1,3 +1,3 @@
1
1
  import { GoogleConfig } from "../../../Config";
2
2
  export declare const authConfig: <K extends keyof GoogleConfig>(key: K) => GoogleConfig[K] | undefined;
3
- export declare const getGoogleCredential: () => import("firebase/auth").OAuthCredential | null;
3
+ export declare const getGoogleCredential: () => import("@firebase/auth").OAuthCredential | null;
@@ -80,5 +80,13 @@ export interface DataProviderAdapter extends ProviderConfigurable {
80
80
  readShallow?(path: string, exception?: boolean): Promise<string[]>;
81
81
  /** Write `data` to `path` in batches (useful for large imports). */
82
82
  setChunks?(path: string, data: object, options?: SetChunksOptions): Promise<void>;
83
+ /**
84
+ * Releases this adapter's underlying connection/resources. Not all providers need one
85
+ * (e.g. a stateless REST-backed adapter has nothing to release) — implement it when the
86
+ * provider holds a long-lived client/channel that should stop retrying once a caller has
87
+ * given up on it (see FirestoreDataProvider, where a nonexistent named database otherwise
88
+ * keeps reconnecting with backoff forever at the SDK level).
89
+ */
90
+ dispose?(): Promise<void>;
83
91
  }
84
92
  export {};
@@ -1,8 +1,26 @@
1
1
  import { DataProviderAdapter, DatabaseOptions, ReadOptions, SetChunksOptions, RecordProps } from './DataProvider';
2
2
  import type { ProviderConfigurationState } from '../ProviderConfiguration';
3
+ export interface FirestoreDataProviderConfig {
4
+ /** Named database within the current app's project — omit for the "(default)" database. */
5
+ databaseId?: string;
6
+ }
3
7
  export declare class FirestoreDataProvider implements DataProviderAdapter {
4
8
  private static listenerRegistered;
5
- constructor();
9
+ private databaseId?;
10
+ constructor(config?: FirestoreDataProviderConfig);
11
+ /** Same "(default)" database as before when no databaseId was configured. */
12
+ private getDb;
13
+ /**
14
+ * Stops this instance's underlying network channel — call this once a caller has given up
15
+ * on this specific databaseId (e.g. after a timeout on a database that doesn't exist).
16
+ * `getFirestore(app, databaseId)` is a cached singleton per (app, databaseId); left alone,
17
+ * a client that can't connect keeps retrying with backoff FOREVER at the SDK level, fully
18
+ * independent of any one `read()`/`subscribe()` call already having given up on its own
19
+ * promise — this is what actually silences that. Safe to call even if never connected
20
+ * (Firestore no-ops); the cache entry is removed afterwards, so a later `new
21
+ * FirestoreDataProvider({databaseId})` for the same id gets a fresh client, not a dead one.
22
+ */
23
+ dispose: () => Promise<void>;
6
24
  getConfigurationState(): ProviderConfigurationState;
7
25
  isConfigured(): boolean;
8
26
  read: (path: string, { where, order, toArray, exception }?: ReadOptions) => Promise<any>;
@@ -0,0 +1,3 @@
1
+ import type { ProviderDescriptor } from '../ProviderDescriptor';
2
+ export type EmailProviderId = 'resend' | 'sendgrid' | 'mailgun' | 'postmark' | 'ses' | 'smtp';
3
+ export declare const EMAIL_PROVIDER_DEFINITIONS: ProviderDescriptor[];
@@ -2,10 +2,10 @@ import { type FirebaseApp } from 'firebase/app';
2
2
  import { type Auth } from "firebase/auth";
3
3
  import { FirebaseConfig } from "../Config";
4
4
  import { type ProviderConfigurationState } from "./ProviderConfiguration";
5
- export declare const setFirebaseConfigState: (config: FirebaseConfig | undefined) => void;
6
- export declare const getFirebaseConfigurationState: () => ProviderConfigurationState;
7
- export declare const getFirestoreConfigurationState: () => ProviderConfigurationState;
8
- export declare const getSafeAuth: () => Auth | null;
5
+ export declare const setFirebaseConfigState: (config: FirebaseConfig | undefined, appName?: string) => void;
6
+ export declare const getFirebaseConfigurationState: (appName?: string) => ProviderConfigurationState;
7
+ export declare const getFirestoreConfigurationState: (appName?: string) => ProviderConfigurationState;
8
+ export declare const getSafeAuth: (appName?: string) => Auth | null;
9
9
  export declare const getFirebaseAuthorization: () => Promise<boolean>;
10
10
  /**
11
11
  * Signs into the currently-initialized Firebase app using a custom token minted
@@ -17,5 +17,11 @@ export declare const getFirebaseAuthorization: () => Promise<boolean>;
17
17
  * Call init(config) to point the app at the right project *before* calling this.
18
18
  */
19
19
  export declare const signInWithFirebaseCustomToken: (token: string) => Promise<boolean>;
20
- declare const init: (config: FirebaseConfig) => Promise<FirebaseApp>;
20
+ declare const init: (config: FirebaseConfig, appName?: string) => Promise<FirebaseApp>;
21
+ /**
22
+ * Invokes a Firebase Callable Function against a given app (the SDK auto-attaches
23
+ * that app's current auth session's ID token — no manual header wiring). Lazily
24
+ * imports 'firebase/functions' so it's not bundled for apps that never call one.
25
+ */
26
+ export declare function callFirebaseFunction<T = unknown>(functionName: string, data: unknown, appName?: string, region?: string): Promise<T>;
21
27
  export default init;
@@ -0,0 +1,29 @@
1
+ import type { ProviderConfigurable } from '../ProviderConfiguration';
2
+ export interface BuildManifest {
3
+ pages: number;
4
+ sizeBytes: number;
5
+ generatedAt: string;
6
+ }
7
+ export interface BuildArtifacts {
8
+ buildId: string;
9
+ outputPath: string;
10
+ manifest: BuildManifest;
11
+ }
12
+ export type DeployOptions = Record<string, never>;
13
+ export interface DeployResult {
14
+ success: boolean;
15
+ buildId: string;
16
+ url?: string;
17
+ error?: string;
18
+ }
19
+ export interface Deployment {
20
+ buildId: string;
21
+ timestamp: string;
22
+ status: 'success' | 'failed' | 'in_progress';
23
+ url?: string;
24
+ }
25
+ export interface PublishProviderAdapter extends ProviderConfigurable {
26
+ deploy(artifacts: BuildArtifacts, options?: DeployOptions): Promise<DeployResult>;
27
+ rollback(buildId: string): Promise<DeployResult>;
28
+ getDeployments(limit?: number): Promise<Deployment[]>;
29
+ }
@@ -0,0 +1,3 @@
1
+ import type { ProviderDescriptor } from '../ProviderDescriptor';
2
+ export type PublishProviderId = 'cloudflare_pages' | 'firebase_hosting' | 'supabase_storage' | 'ftp' | 'sftp' | 'netlify' | 'github_pages' | 's3_cloudfront' | 'static_export';
3
+ export declare const PUBLISH_PROVIDER_DEFINITIONS: ProviderDescriptor[];
@@ -1,8 +1,14 @@
1
1
  import type { StorageProviderAdapter, UploadOptions, StorageOptions, DeleteOptions, MoveOptions, ListOptions, StorageFileInfo, UploadHandle } from './StorageProvider';
2
2
  import type { ProviderConfigurationState } from '../ProviderConfiguration';
3
+ export interface FirebaseStorageProviderConfig {
4
+ /** Used when a call doesn't pass its own `opts.bucket` — omit for the project's default bucket. */
5
+ defaultBucket?: string;
6
+ }
3
7
  export declare class FirebaseStorageProvider implements StorageProviderAdapter {
4
8
  private static listenerRegistered;
5
- constructor();
9
+ private defaultBucket?;
10
+ constructor(config?: FirebaseStorageProviderConfig);
11
+ private resolveBucket;
6
12
  getConfigurationState(): ProviderConfigurationState;
7
13
  isConfigured(): boolean;
8
14
  upload: (file: string | File | Blob, path: string, opts?: UploadOptions) => Promise<string | undefined>;
package/dist/vite.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u="x-llmnative-proxy",p="/api/proxy",h=async t=>{const e=[];for await(const r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(r));return e.length===0?void 0:Buffer.concat(e)},l=async(t,e,r)=>{const a=new URL(t.url||"/","http://localhost").searchParams.get("url");if(t.headers[u]!=="1"){e.statusCode=403,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:"Proxy access denied."}));return}if(!a){e.statusCode=400,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:'Missing "url" query parameter.'}));return}try{const o=new URL(a);if(o.pathname.startsWith(r)&&["localhost","127.0.0.1"].includes(o.hostname)){e.statusCode=508,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:"Recursive proxy target detected.",target:a}));return}const d=await h(t),f=new Headers,y=new Set([u,"host","origin","referer","content-length","transfer-encoding","connection"]);Object.entries(t.headers).forEach(([i,n])=>{!n||y.has(i.toLowerCase())||f.set(i,Array.isArray(n)?n.join(", "):n)});const c=await fetch(a,{method:t.method||"GET",headers:f,body:d&&!["GET","HEAD"].includes((t.method||"GET").toUpperCase())?d:void 0,redirect:"follow"});e.statusCode=c.status,c.headers.forEach((i,n)=>{n.toLowerCase()!=="content-encoding"&&e.setHeader(n,i)}),e.end(Buffer.from(await c.arrayBuffer()))}catch(o){e.statusCode=502,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:o instanceof Error?o.message:"Proxy request failed."}))}},g=(t=p)=>({name:"llmnative-dev-proxy",configureServer(e){e.middlewares.use(t,(r,s)=>{l(r,s,t)})},configurePreviewServer(e){e.middlewares.use(t,(r,s)=>{l(r,s,t)})}});exports.PROXY_PATH=p;exports.createProxyPlugin=g;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`x-llmnative-proxy`,t=`/api/proxy`,n=async e=>{let t=[];for await(let n of e)t.push(Buffer.isBuffer(n)?n:Buffer.from(n));return t.length===0?void 0:Buffer.concat(t)},r=async(t,r,i)=>{let a=new URL(t.url||`/`,`http://localhost`).searchParams.get(`url`);if(t.headers[e]!==`1`){r.statusCode=403,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Proxy access denied.`}));return}if(!a){r.statusCode=400,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Missing "url" query parameter.`}));return}try{let o=new URL(a);if(o.pathname.startsWith(i)&&[`localhost`,`127.0.0.1`].includes(o.hostname)){r.statusCode=508,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Recursive proxy target detected.`,target:a}));return}let s=await n(t),c=new Headers,l=new Set([e,`host`,`origin`,`referer`,`content-length`,`transfer-encoding`,`connection`]);Object.entries(t.headers).forEach(([e,t])=>{!t||l.has(e.toLowerCase())||c.set(e,Array.isArray(t)?t.join(`, `):t)});let u=await fetch(a,{method:t.method||`GET`,headers:c,body:s&&![`GET`,`HEAD`].includes((t.method||`GET`).toUpperCase())?Uint8Array.from(s):void 0,redirect:`follow`});r.statusCode=u.status,u.headers.forEach((e,t)=>{t.toLowerCase()!==`content-encoding`&&r.setHeader(t,e)}),r.end(Buffer.from(await u.arrayBuffer()))}catch(e){r.statusCode=502,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:e instanceof Error?e.message:`Proxy request failed.`}))}},i=(e=t)=>({name:`llmnative-dev-proxy`,configureServer(t){t.middlewares.use(e,(t,n)=>{r(t,n,e)})},configurePreviewServer(t){t.middlewares.use(e,(t,n)=>{r(t,n,e)})}});exports.PROXY_PATH=t,exports.createProxyPlugin=i;
package/dist/vite.mjs CHANGED
@@ -1,54 +1,63 @@
1
- const u = "x-llmnative-proxy", l = "/api/proxy", y = async (t) => {
2
- const e = [];
3
- for await (const r of t)
4
- e.push(Buffer.isBuffer(r) ? r : Buffer.from(r));
5
- return e.length === 0 ? void 0 : Buffer.concat(e);
6
- }, p = async (t, e, r) => {
7
- const a = new URL(t.url || "/", "http://localhost").searchParams.get("url");
8
- if (t.headers[u] !== "1") {
9
- e.statusCode = 403, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: "Proxy access denied." }));
10
- return;
11
- }
12
- if (!a) {
13
- e.statusCode = 400, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: 'Missing "url" query parameter.' }));
14
- return;
15
- }
16
- try {
17
- const o = new URL(a);
18
- if (o.pathname.startsWith(r) && ["localhost", "127.0.0.1"].includes(o.hostname)) {
19
- e.statusCode = 508, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: "Recursive proxy target detected.", target: a }));
20
- return;
21
- }
22
- const d = await y(t), f = new Headers(), h = /* @__PURE__ */ new Set([u, "host", "origin", "referer", "content-length", "transfer-encoding", "connection"]);
23
- Object.entries(t.headers).forEach(([i, n]) => {
24
- !n || h.has(i.toLowerCase()) || f.set(i, Array.isArray(n) ? n.join(", ") : n);
25
- });
26
- const c = await fetch(a, {
27
- method: t.method || "GET",
28
- headers: f,
29
- body: d && !["GET", "HEAD"].includes((t.method || "GET").toUpperCase()) ? d : void 0,
30
- redirect: "follow"
31
- });
32
- e.statusCode = c.status, c.headers.forEach((i, n) => {
33
- n.toLowerCase() !== "content-encoding" && e.setHeader(n, i);
34
- }), e.end(Buffer.from(await c.arrayBuffer()));
35
- } catch (o) {
36
- e.statusCode = 502, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: o instanceof Error ? o.message : "Proxy request failed." }));
37
- }
38
- }, g = (t = l) => ({
39
- name: "llmnative-dev-proxy",
40
- configureServer(e) {
41
- e.middlewares.use(t, (r, s) => {
42
- p(r, s, t);
43
- });
44
- },
45
- configurePreviewServer(e) {
46
- e.middlewares.use(t, (r, s) => {
47
- p(r, s, t);
48
- });
49
- }
1
+ //#region src/providers/proxy/vite.ts
2
+ var e = "x-llmnative-proxy", t = "/api/proxy", n = async (e) => {
3
+ let t = [];
4
+ for await (let n of e) t.push(Buffer.isBuffer(n) ? n : Buffer.from(n));
5
+ return t.length === 0 ? void 0 : Buffer.concat(t);
6
+ }, r = async (t, r, i) => {
7
+ let a = new URL(t.url || "/", "http://localhost").searchParams.get("url");
8
+ if (t.headers[e] !== "1") {
9
+ r.statusCode = 403, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: "Proxy access denied." }));
10
+ return;
11
+ }
12
+ if (!a) {
13
+ r.statusCode = 400, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: "Missing \"url\" query parameter." }));
14
+ return;
15
+ }
16
+ try {
17
+ let o = new URL(a);
18
+ if (o.pathname.startsWith(i) && ["localhost", "127.0.0.1"].includes(o.hostname)) {
19
+ r.statusCode = 508, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({
20
+ error: "Recursive proxy target detected.",
21
+ target: a
22
+ }));
23
+ return;
24
+ }
25
+ let s = await n(t), c = new Headers(), l = /* @__PURE__ */ new Set([
26
+ e,
27
+ "host",
28
+ "origin",
29
+ "referer",
30
+ "content-length",
31
+ "transfer-encoding",
32
+ "connection"
33
+ ]);
34
+ Object.entries(t.headers).forEach(([e, t]) => {
35
+ !t || l.has(e.toLowerCase()) || c.set(e, Array.isArray(t) ? t.join(", ") : t);
36
+ });
37
+ let u = await fetch(a, {
38
+ method: t.method || "GET",
39
+ headers: c,
40
+ body: s && !["GET", "HEAD"].includes((t.method || "GET").toUpperCase()) ? Uint8Array.from(s) : void 0,
41
+ redirect: "follow"
42
+ });
43
+ r.statusCode = u.status, u.headers.forEach((e, t) => {
44
+ t.toLowerCase() !== "content-encoding" && r.setHeader(t, e);
45
+ }), r.end(Buffer.from(await u.arrayBuffer()));
46
+ } catch (e) {
47
+ r.statusCode = 502, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: e instanceof Error ? e.message : "Proxy request failed." }));
48
+ }
49
+ }, i = (e = t) => ({
50
+ name: "llmnative-dev-proxy",
51
+ configureServer(t) {
52
+ t.middlewares.use(e, (t, n) => {
53
+ r(t, n, e);
54
+ });
55
+ },
56
+ configurePreviewServer(t) {
57
+ t.middlewares.use(e, (t, n) => {
58
+ r(t, n, e);
59
+ });
60
+ }
50
61
  });
51
- export {
52
- l as PROXY_PATH,
53
- g as createProxyPlugin
54
- };
62
+ //#endregion
63
+ export { t as PROXY_PATH, i as createProxyPlugin };