outlet-orm 6.0.0 → 7.0.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.
package/types/index.d.ts CHANGED
@@ -153,6 +153,20 @@ declare module 'outlet-orm' {
153
153
  to: number;
154
154
  }
155
155
 
156
+ /** Observer interface for model lifecycle events */
157
+ export interface ModelObserver<T extends Model = Model> {
158
+ creating?(model: T): boolean | void | Promise<boolean | void>;
159
+ created?(model: T): void | Promise<void>;
160
+ updating?(model: T): boolean | void | Promise<boolean | void>;
161
+ updated?(model: T): void | Promise<void>;
162
+ saving?(model: T): boolean | void | Promise<boolean | void>;
163
+ saved?(model: T): void | Promise<void>;
164
+ deleting?(model: T): boolean | void | Promise<boolean | void>;
165
+ deleted?(model: T): void | Promise<void>;
166
+ restoring?(model: T): boolean | void | Promise<boolean | void>;
167
+ restored?(model: T): void | Promise<void>;
168
+ }
169
+
156
170
  export class QueryBuilder<T extends Model> {
157
171
  constructor(model: typeof Model);
158
172
 
@@ -204,6 +218,12 @@ declare module 'outlet-orm' {
204
218
  get(): Promise<T[]>;
205
219
  first(): Promise<T | null>;
206
220
  firstOrFail(): Promise<T>;
221
+ /** Get the first record matching current wheres or create a new one */
222
+ firstOrCreate(values?: Record<string, any>): Promise<T>;
223
+ /** Get the first record matching current wheres or return a new unsaved instance */
224
+ firstOrNew(values?: Record<string, any>): Promise<T>;
225
+ /** Find a record matching current wheres and update it, or create a new one */
226
+ updateOrCreate(values?: Record<string, any>): Promise<T>;
207
227
  paginate(page?: number, perPage?: number): Promise<PaginationResult<T>>;
208
228
  count(): Promise<number>;
209
229
  exists(): Promise<boolean>;
@@ -214,6 +234,8 @@ declare module 'outlet-orm' {
214
234
  delete(): Promise<any>;
215
235
  increment(column: string, amount?: number): Promise<any>;
216
236
  decrement(column: string, amount?: number): Promise<any>;
237
+ /** Lazily iterate over matching records using an async generator */
238
+ cursor(chunkSize?: number): AsyncGenerator<T, void, unknown>;
217
239
 
218
240
  clone(): QueryBuilder<T>;
219
241
  }
@@ -344,6 +366,25 @@ declare module 'outlet-orm' {
344
366
  static whereNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
345
367
  static whereNotNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
346
368
  static count(): Promise<number>;
369
+
370
+ // Convenience query methods
371
+ /** Find the first record matching conditions or create a new one */
372
+ static firstOrCreate<T extends Model>(this: new () => T, conditions: Record<string, any>, values?: Record<string, any>): Promise<T>;
373
+ /** Find the first record matching conditions or return a new unsaved instance */
374
+ static firstOrNew<T extends Model>(this: new () => T, conditions: Record<string, any>, values?: Record<string, any>): Promise<T>;
375
+ /** Find a record matching conditions and update it, or create a new one */
376
+ static updateOrCreate<T extends Model>(this: new () => T, conditions: Record<string, any>, values?: Record<string, any>): Promise<T>;
377
+ /** Insert or update multiple records in bulk (ON CONFLICT / ON DUPLICATE KEY) */
378
+ static upsert(rows: Record<string, any>[], uniqueBy: string | string[], update?: string[]): Promise<any>;
379
+
380
+ // Observer
381
+ /** Register an observer class that listens to model lifecycle events */
382
+ static observe(observer: ModelObserver | (new () => ModelObserver)): void;
383
+
384
+ // Cursor / Stream
385
+ /** Lazily iterate over all matching records using an async generator */
386
+ static cursor<T extends Model>(this: new () => T, chunkSize?: number): AsyncGenerator<T, void, unknown>;
387
+
347
388
  static with<T extends Model>(this: new () => T, ...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): QueryBuilder<T>;
348
389
  /** Include hidden attributes in query results */
349
390
  static withHidden<T extends Model>(this: new () => T): QueryBuilder<T>;
@@ -896,4 +937,110 @@ declare module 'outlet-orm' {
896
937
  on(event: 'serverEvent', listener: (payload: Record<string, any>) => void): this;
897
938
  on(event: string, listener: (...args: any[]) => void): this;
898
939
  }
940
+
941
+ // ==================== AI Integration (v7.0.0) ====================
942
+
943
+ /** MCP tool definition */
944
+ export interface MCPToolDefinition {
945
+ name: string;
946
+ description: string;
947
+ inputSchema: {
948
+ type: 'object';
949
+ properties: Record<string, any>;
950
+ required: string[];
951
+ };
952
+ }
953
+
954
+ /** MCP server options */
955
+ export interface MCPServerOptions {
956
+ /** DatabaseConnection instance (optional, auto-loaded from project) */
957
+ connection?: DatabaseConnection;
958
+ /** Project root directory (default: process.cwd()) */
959
+ projectDir?: string;
960
+ /** Enable AI safety guardrails (default: true) */
961
+ safetyGuardrails?: boolean;
962
+ }
963
+
964
+ /** JSON-RPC 2.0 message */
965
+ export interface JSONRPCMessage {
966
+ jsonrpc: '2.0';
967
+ id?: number | string;
968
+ method?: string;
969
+ params?: Record<string, any>;
970
+ result?: any;
971
+ error?: { code: number; message: string };
972
+ }
973
+
974
+ /** MCP Server — exposes ORM capabilities to AI agents via JSON-RPC 2.0 */
975
+ export class MCPServer {
976
+ constructor(options?: MCPServerOptions);
977
+
978
+ /** Project root directory */
979
+ projectDir: string;
980
+ /** Whether safety guardrails are enabled */
981
+ safetyGuardrails: boolean;
982
+
983
+ /** Start the MCP server on stdio */
984
+ start(): void;
985
+ /** Get a programmatic handler function (for testing/embedding) */
986
+ handler(): (message: JSONRPCMessage) => Promise<JSONRPCMessage | null>;
987
+ /** Graceful shutdown */
988
+ close(): Promise<void>;
989
+
990
+ on(event: 'started', listener: () => void): this;
991
+ on(event: 'initialized', listener: () => void): this;
992
+ on(event: 'response', listener: (response: JSONRPCMessage) => void): this;
993
+ on(event: 'close', listener: () => void): this;
994
+ on(event: string, listener: (...args: any[]) => void): this;
995
+ }
996
+
997
+ /** Agent detection result */
998
+ export interface AgentDetectionResult {
999
+ /** Whether an AI agent was detected */
1000
+ detected: boolean;
1001
+ /** Name of the detected agent (null if not detected) */
1002
+ agentName: string | null;
1003
+ }
1004
+
1005
+ /** Destructive action validation result */
1006
+ export interface DestructiveActionResult {
1007
+ /** Whether the action is allowed */
1008
+ allowed: boolean;
1009
+ /** Message explaining why action was blocked (empty if allowed) */
1010
+ message: string;
1011
+ }
1012
+
1013
+ /** AI Safety Guardrails — detects AI agents and protects against destructive operations */
1014
+ export class AISafetyGuardrails {
1015
+ /** Detect if the current process is invoked by an AI agent */
1016
+ static detectAgent(): AgentDetectionResult;
1017
+ /** Check if a CLI command is destructive */
1018
+ static isDestructiveCommand(command: string): boolean;
1019
+ /** Validate whether user consent is present for a destructive operation */
1020
+ static validateDestructiveAction(command: string, flags?: { consent?: string; yes?: boolean; force?: boolean }): DestructiveActionResult;
1021
+ /** The environment variable name for AI consent */
1022
+ static readonly CONSENT_ENV_VAR: string;
1023
+ }
1024
+
1025
+ /** Prompt blueprint — parsed from a natural language description */
1026
+ export interface PromptBlueprint {
1027
+ /** Detected domain (e.g. 'blog', 'e-commerce', 'saas') */
1028
+ domain: string;
1029
+ /** Table definitions */
1030
+ tables: Record<string, { columns: string[]; pivot?: boolean }>;
1031
+ /** Match confidence score */
1032
+ score: number;
1033
+ }
1034
+
1035
+ /** Prompt Generator — generates projects from natural language descriptions */
1036
+ export class PromptGenerator {
1037
+ /** Parse a natural language prompt into a project blueprint */
1038
+ static parse(prompt: string): PromptBlueprint;
1039
+ /** Generate model files from a blueprint */
1040
+ static generateModels(blueprint: PromptBlueprint, outputDir: string): string[];
1041
+ /** Generate migration files from a blueprint */
1042
+ static generateMigrations(blueprint: PromptBlueprint, outputDir: string): string[];
1043
+ /** Generate a seeder file from a blueprint */
1044
+ static generateSeeder(blueprint: PromptBlueprint, outputDir: string): string;
1045
+ }
899
1046
  }