@fluentity/core
Version:
Fluentity is a fluent, model-oriented, typed HTTP client for TypeScript and framework agnostic.
235 lines (234 loc) • 7.67 kB
TypeScript
import { MethodType } from './index';
import { Attributes, Model } from './Model';
import { RelationBuilder } from './RelationBuilder';
/**
* Builder class for has-many relationships between models.
* Provides methods for managing a one-to-many relationship with another model.
* Used when a model has multiple related model instances.
*
* Features:
* - Collection retrieval and filtering
* - Model creation
* - Model updates
* - Model deletion
* - Pagination support
* - Relationship traversal
*
* @template T - The type of model this relation builder works with
* @example
* ```typescript
* // Basic usage in a model
* class User extends Model {
* @HasMany(() => Post)
* posts: Post[];
* }
*
* // Usage in queries
* const posts = await user.posts.all();
* const post = await user.posts.create({ title: 'New Post' });
* await user.posts.update(123, { title: 'Updated Post' });
* await user.posts.delete(123);
* ```
*/
export declare class HasManyRelationBuilder<T extends Model<Attributes>> extends RelationBuilder<T> {
/**
* Fetches all related model instances.
* Makes a GET request to retrieve all related models.
* Use with caution for large collections - consider using pagination.
*
* @returns A promise that resolves to an array of related model instances
* @throws {Error} If the request fails
* @example
* ```typescript
* // Get all posts
* const posts = await user.posts.all();
* console.log(`Found ${posts.length} posts`);
*
* // Get with filtering
* const posts = await user.posts
* .where({ status: 'published' })
* .orderBy('created_at', 'desc')
* .all();
*
* // Get with error handling
* try {
* const posts = await user.posts.all();
* console.log('Posts loaded successfully');
* } catch (error) {
* console.error('Error loading posts:', error);
* }
*
* // Use in relationship chain
* const user = await User.find(123);
* const comments = await user.posts
* .find(456)
* .comments
* .all();
* ```
*/
all(): Promise<T[]>;
/**
* Creates a new related model instance.
* Makes a POST request to create a new related model.
* The new model is automatically associated with the parent model.
*
* @param data - The data to create the new model with
* @returns A promise that resolves to the created model instance
* @throws {Error} If the creation fails
* @example
* ```typescript
* // Create a new post
* const post = await user.posts.create({
* title: 'New Post',
* content: 'Post content',
* status: 'draft'
* });
*
* // Create with error handling
* try {
* const post = await user.posts.create({
* title: 'New Post',
* content: 'Post content'
* });
* console.log(`Created post with ID: ${post.id}`);
* } catch (error) {
* if (error.status === 422) {
* console.log('Validation failed:', error.errors);
* } else {
* console.error('Error creating post:', error);
* }
* }
*
* // Create in relationship chain
* const user = await User.find(123);
* const comment = await user.posts
* .find(456)
* .comments
* .create({ content: 'Great post!' });
* ```
*/
create<A extends Partial<Attributes>>(data: A): Promise<T>;
/**
* Deletes a related model instance by ID.
* Makes a DELETE request to remove a specific related model.
* The local instance remains but becomes detached from the server.
*
* @param id - The ID of the model to delete
* @returns A promise that resolves when the deletion is complete
* @throws {Error} If the deletion fails
* @example
* ```typescript
* // Delete a post
* await user.posts.delete(123);
*
* // Delete with error handling
* try {
* await user.posts.delete(123);
* console.log('Post deleted successfully');
* } catch (error) {
* if (error.status === 404) {
* console.log('Post not found');
* } else {
* console.error('Error deleting post:', error);
* }
* }
*
* // Delete in relationship chain
* const user = await User.find(123);
* await user.posts
* .find(456)
* .comments
* .delete(789);
* ```
*/
delete(id: string | number): Promise<void>;
/**
* Updates a related model instance by ID.
* Makes a PUT/PATCH request to update a specific related model.
* Can use either PUT (full update) or PATCH (partial update).
*
* @param id - The ID of the model to update
* @param data - The data to update the model with
* @param method - The HTTP method to use (PUT or PATCH)
* @returns A promise that resolves to the updated model instance
* @throws {Error} If the update fails
* @example
* ```typescript
* // Full update with PUT
* const post = await user.posts.update(123, {
* title: 'Updated Title',
* content: 'Updated content',
* status: 'published'
* });
*
* // Partial update with PATCH
* const post = await user.posts.update(123, {
* title: 'Updated Title'
* }, Methods.PATCH);
*
* // Update with error handling
* try {
* const post = await user.posts.update(123, {
* title: 'Updated Title'
* });
* console.log('Post updated successfully');
* } catch (error) {
* if (error.status === 404) {
* console.log('Post not found');
* } else if (error.status === 422) {
* console.log('Validation failed:', error.errors);
* } else {
* console.error('Error updating post:', error);
* }
* }
*
* // Update in relationship chain
* const user = await User.find(123);
* const comment = await user.posts
* .find(456)
* .comments
* .update(789, { content: 'Updated comment' });
* ```
*/
update<A extends Partial<Attributes>>(id: string | number, data: A, method?: MethodType): Promise<T>;
/**
* Fetches a paginated list of related model instances.
* Makes a GET request with pagination parameters.
* Combines page number and size into limit/offset parameters.
*
* @param page - The page number to fetch (default: 1)
* @param perPage - The number of items per page (default: 10)
* @returns A promise that resolves to an array of related model instances
* @throws {Error} If the request fails
* @example
* ```typescript
* // Get first page with 20 items
* const posts = await user.posts.paginate(1, 20);
*
* // Get second page with default size
* const posts = await user.posts.paginate(2);
*
* // Get with filtering
* const posts = await user.posts
* .where({ status: 'published' })
* .orderBy('created_at', 'desc')
* .paginate(2, 20);
*
* // Paginate with error handling
* try {
* const posts = await user.posts.paginate(2, 20);
* console.log(`Found ${posts.length} posts on page 2`);
* } catch (error) {
* console.error('Error fetching posts:', error);
* }
*
* // Paginate in relationship chain
* const user = await User.find(123);
* const comments = await user.posts
* .find(456)
* .comments
* .paginate(2, 20);
* ```
*/
paginate(page?: number, perPage?: number): Promise<T[]>;
}