एपीआई के तैयार होने से पहले एक फ्रन्टएण्ड बनाना; बिना परिश्रम के (हिन्दी (Hindi))

एपीआई के तैयार होने से पहले एक फ्रन्टएण्ड बनाना; बिना परिश्रम के

Saturday, 13 December 2025

//

19 minute read

परिचय

कितने बार आपको बैकएण्ड एपीआई्स के लिए इंतज़ार करना बंद कर दिया गया है?

प्रविष्ट करें mostlylucid.mockllmapi - एक उत्पादन को तैयार करने और कॉल राज्य की याद रखने के लिए।

क्या यह समर्थन करता है: हर प्रोटोकॉल आप की जरूरत है - RPREPC, gPC, SPC, SPRC, SPR, सर्वर-SC घटनाओं, और खोलें MPPEPEPEPEC. निश्चित रूप से प्रतिक्रियाओं को अपने संदर्भ पर आधारित किया जाता है, बहु-प्रयोगी कार्य कार्य और जटिल जाँच सरल बना रहे हैं.

परियोजना कड़ियाँ

लागू नहीं लागू नहीं GiB से जारी लाइसेंस: अनसब्सक्राइब करें

इसे इस्तेमाल करने के तीन तरीके

आप ज़्यादातर का उपयोग तीन तरीकों से कर सकते हैं, पर निर्भर करता है कि आप किस तरह के पृथक वातावरण को चाहते हैं:

  1. एनईएस. - अपने मौजूदा परियोजना में जोड़ें
  2. पृथक क्लिक औज़ार - क्रास- बिल्डर एक्जीक्यूटेबल (सेविएंट) रिलीज)
  3. डॉकएण्ड कंटेनर - शून्य संस्थापन आवश्यक

खूनी विशेषता: कॉन्टेक्स्ट मेमोरी

वेस्टर्न पूरा मार्गदर्शक: एपीआई संदर्भ दस्तावेज़ीकरण

पारंपरिक हंसी के लिए एक गंभीर गलती है: प्रत्येक अनुरोध स्वतंत्र है. आईडी 42 के साथ एक उपयोक्ता प्राप्त करें, फिर उनके आदेशों को लाने के लिए, और आप प्रयोक्ता ID 99 के लिए आदेश मिलेगा. कोई सुसंगतता नहीं है.

एपीआई संदर्भ इस साझा मेमोरी को संबंधित निवेदन के पार हल करें:

// Request 1: Get a user
// Note: 'context' is a simple query parameter - no cookies or sessions needed
fetch('/api/users/123?context=checkout-session')
// Response: { id: 42, name: "Alice Smith", email: "[email protected]" }

// Request 2: Get orders (same context parameter)
fetch('/api/orders?userId=42&context=checkout-session')
// Response: { userId: 42, customerName: "Alice Smith", items: [...] }
// Perfect! Same user, consistent data

LLM एक ही संदर्भ में पिछले निवेदनों को देखता है और सतत डाटा बनाता है. यह बहु- चरण कार्य प्रवाह के लिए खेल- बदलावकर्ता है.

विशेषताएँ:

उठने की संभावना:

  • स्वचालित एक्सपोजर के 15 मिनट के बीतने पर (कॉन्फ़िगरेबल)
  • हर निवेदन टाइमर ताज़ा करता है

व्यवहार:

  • प्रतिक्रिया से सभी क्षेत्रों की सहजता

सुरक्षा:

  • शून्य स्मृति रिसाव - संदर्भ खुद को साफ करता है

केस इस्तेमाल करें:

  • सीआई/सीडी के लिए सही है - चलाने के बीच कोई स्थिति नहीं है

क्विक स्टार्ट

विकल्प 1: नॉइए पैकेज

dotnet add package mostlylucid.mockllmapi
// Program.cs
builder.Services.AddLLMockApi(builder.Configuration);
app.MapLLMockApi("/api/mock");

विकल्प 2: क्लिक करने पर औजार

# Download from https://github.com/scottgal/LLMApi/releases
llmock serve --port 5000

विकल्प 3: डॉकर

वेस्टर्न पूर्ण मार्गदर्शक: डॉक लेसर मार्गदर्शन

git clone https://github.com/scottgal/LLMApi.git
cd LLMApi
docker compose up -d

प्रीएक्सईसी बैकएण्ड:

आप की जरूरत है एक का: ओलमा, ओपन - रीडला, या LM छात्रियो:

# Recommended: Ollama with ministral-3:3b (ultra-fast, accurate JSON generation)
ollama pull ministral-3:3b

देखें ओसमा मॉडल्स मार्गदर्शक सभी आदर्श सलाह और तुलनाओं के लिए

तत्काल कोशिश करें

एक बार चल रहा है, अपनी पहली गुज़ारिश कीजिए:

curl http://localhost:5000/api/mock/users
# Response: [{"id": 1, "name": "Alice Johnson", "email": "[email protected]"}, ...]

यही कारण है कि अब आप एक काम कर रहे एपीआई है जो माँग पर यथार्थवादी डेटा बनाता है।

वास्तविक उदाहरण: ज़्यादातर लोगों की खोज.net

इस ब्लॉग से वास्तविक सर्च कोड है - यह असक्रिय उत्पादन फ्रन्टएण्ड कोड हैउपहास के लिए आवश्यक कोई अनुकूलनशीलता नहीं:

// typeahead.js from mostlylucid.net
export function typeahead() {
    return {
        query: '',
        results: [],
        search() {
            fetch(`/api/search/${encodeURIComponent(this.query)}`)
                .then(response => response.json())
                .then(data => { this.results = data; });
        }
    }
}

इसे हँसी में डाल दो:

# Using CLI
llmock serve --port 5000

# Query returns contextual results
curl http://localhost:5000/api/search/markdown
# LLM generates blog posts about Markdown

curl http://localhost:5000/api/search/docker
# LLM generates blog posts about Docker

हर जवाब अनोखा और यथार्थवादी है, और इस प्रश्‍न के अनुकूल है ।

नियंत्रण को आकार दें: अपनी योजना पारिभाषित करें

सिर्फ बेतरतीब डेटा बनाने के अलावा, आपको अकसर JSON संरचना के ऊपर सटीक नियंत्रण की आवश्यकता होती है. आकार नियंत्रण आप वास्तव में क्या LLLM बता देता है - सामने के विकास के लिए सबसे शक्तिशाली सुविधा.

मूल आकार

# Without shape - random structure
curl http://localhost:5000/api/mock/users
# Response: { "userId": 1, "fullName": "Alice" }

# With shape - you control it
curl "http://localhost:5000/api/mock/users" \
  -H 'X-Response-Shape: {"id":0,"name":"string","email":"string"}'
# Response: { "id": 1, "name": "Alice", "email": "[email protected]" }

आकार निर्दिष्ट करने के लिए तीन तरीके:

  1. क्वैरी पैरामीटर - ?shape={...}
  2. एचटीटीपी शीर्षिका - X-Response-Shape: {...} (अनुशंसित)
  3. निवेदन शरीर - {"shape": {...}}

संजालित आकार

const shape = {
  company: {
    id: 0,
    name: "string",
    employees: [{
      id: 0,
      firstName: "string",
      department: { id: 0, name: "string" },
      projects: [{ id: 0, title: "string" }]
    }]
  }
};

fetch('/api/mock/company', {
  headers: { 'X-Response-Shape': JSON.stringify(shape) }
});

लिपि पंक्तिबद्धता टाइप करें

interface User {
  id: number;
  name: string;
  email: string;
}

const USER_SHAPE: Partial<User> = { id: 0, name: "", email: "" };

// Shape becomes your type definition AND mock schema!

कॉन्टेक्स्ट के साथ बहु- स्टेप कार्य

अब चलो API संदर्भ को हैंडल करने के लिए tras के साथ आकार को जोड़ते हैं, विविध चरणों के फूल. संदर्भ मेमोरी सुविधा याद रखें पहले से? यहाँ है कैसे यह वास्तव में विश्वीय संचालन में प्रकाश।

यह उदाहरण ज़्यादातर क्विन्सन के अनुवाद सेवा से दिखाता है कि कैसे सीनेटएम पूर्ण अतुल्यकालिक कार्य प्रवाह के दौरान राज्य को बनाए रखता है:

# Step 1: Start translation
curl -X POST http://localhost:5000/api/translate/start?context=translate-session \
  -d '{"language": "es", "markdown": "# Hello World"}'
# Response: { "taskId": "abc-123", "status": "processing" }

# Step 2: Check status (LLM remembers the task)
curl http://localhost:5000/api/translate/status/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "status": "complete" }

# Step 3: Get result (same taskId!)
curl http://localhost:5000/api/translate/result/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "translatedText": "# Hola Mundo" }

ध्यान दें कि कैसे taskId सभी निवेदनों के पार सतत है. संदर्भ यह संभव बनाता है.

सभी प्रोटोकॉल

अब तक हम Race पर ध्यान केंद्रित किया है, लेकिन आधुनिक अनुप्रयोग अधिक की जरूरत है. क्या आप ग्राफQL के साथ निर्माण कर रहे हैं, सिग्नलR के साथ असली समय विशेषताओं को लागू कर रहे हैं या gRCMC सेवा के साथ काम कर रहे हैं, ज़्यादातर uci.moli ने आपको कवरी पर कवर किया है.

समर्थित प्रोटोकॉलः

  • एलआईएसटी
  • ज्यूक ग्राफ
  • RRPC
  • सिग्नलआर
  • STUN सर्वर-S घटनाएँ (SS)
  • WALEKS ओपनआई / STYESCKS

ग्राफ

वेस्टर्न गाइड: ग्राफ

curl -X POST http://localhost:5000/api/mock/graphql \
  -d '{"query": "{ users { id name email } }"}'

क्वैरी आकार है - कोई अलग स्कीमा आवश्यक नहीं.

जीपीसी

वेस्टर्न पूर्ण मार्गदर्शक: सीपीसी समर्थन

# Upload .proto file
curl -X POST http://localhost:5116/api/grpc-protos \
  --data-binary "@user_service.proto"

# Call via JSON or binary Protobuf
curl -X POST http://localhost:5116/api/grpc/userservice/UserService/GetUser \
  -d '{"user_id": 123}'

सिग्नल-R सही समय

वेस्टर्न गाइड: सिग्नल-आर डेमो गाइडGenericName

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hub/mock")
    .build();

connection.on("DataUpdate", (message) => {
    console.log(message.data); // Live generated data
});

await connection.start();
await connection.invoke("SubscribeToContext", "stock-prices");

निर्माण के लिए बिल्कुल सही है.

सर्वर-S घटनाएँ (S)

वेस्टर्न गाइड: एसईईएस स्ट्रीमिंग मोड

const eventSource = new EventSource('/api/mock/stream/users');
eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Token:', data.chunk); // Progressive generation
};

MHAG / SESYEANSE

वेस्टर्न पूर्ण मार्गदर्शक: ओपनपीआई विशेषताएँ

# CLI: Load any OpenAPI spec
llmock serve --spec https://petstore3.swagger.io/api/v3/openapi.json

# All endpoints become live mocks automatically
curl http://localhost:5000/petstore/pet/123

प्लगइनेबल औज़ार: मिक्स वास्तविक डाटा (p)

वेस्टर्न पूर्ण मार्गदर्शक: औज़ार क्रियाएँ (O)

कभी - कभी आपको एक नयी - नयी जानकारी की ज़रूरत पड़ती है, साथ ही साथ उत्पादन से वास्तविक जानकारी की ज़रूरत होती है ।

{
  "Tools": [{
    "Name": "getUserData",
    "Type": "http",
    "HttpConfig": {
      "Endpoint": "https://api.production.com/users/{userId}",
      "Headers": { "Authorization": "Bearer ${PROD_API_KEY}" }
    }
  }]
}
curl "http://localhost:5000/api/mock/orders?useTool=getUserData&userId=123"

उपहास उपयोगकर्ता डाटा लाता है, फिर LLM इसके उपयोग से आदेश बनाता है. पैंक्रियाज़ के साथ यथार्थवादी जाँच के लिए अधिक उपयोगी है.

यु. पू.

अगर आप एक अनजाने में निर्माण कर रहे हैं. वेर, एकीकरण है समुद्रीय है. इस तरह की खूबसूरती है शून्य कोड परिवर्तन आपके सेवाओं के लिए - आप बस कॉन्फ़िगर करें HttpClient विकास के दौरान और उत्पादन में वास्तविक एपीआई पर विचार करने के लिए ।

// Real code from mostlylucid.net
builder.Services.AddHttpClient<IMarkdownTranslatorService, MarkdownTranslatorService>(
    client => {
        var baseUrl = builder.Configuration["TranslationService:BaseUrl"]
            ?? "http://localhost:5000";  // Mock during dev
        client.BaseAddress = new Uri(baseUrl);
    }
);

एएस- एडिस्कमेंट्स. डी.सन:

{
  "TranslationService": {
    "BaseUrl": "http://localhost:5000"  // Mock
  }
}

एप्रेशन्स. prodin.jon:

{
  "TranslationService": {
    "BaseUrl": "https://api.production.com"  // Real
  }
}

यह पैटर्न किसी के लिए काम करता है HttpClient आपके अनुप्रयोग - अनुवाद सेवाओं में, भुगतान द्वार, बाहरी एपीआई्स, आप इसका नाम देते हैं ।

इसे इस्तेमाल करने के लिए

इससे पहले कि हम विस्तृत विशेषताओं में कटौती करें, हम इस उपकरण के बारे में स्पष्ट हो जब यह आपके काम फूल के लिए अर्थ बनाता है।

के लिए बिल्कुल सही:

  • बैकएण्ड मौजूद होने से पहले फ्रन्टएण्ड विकास - बैकेंड टीमों पर ब्लॉकिंग बंद करें
  • मल्टी- स्टेप कार्य जांच - कॉन्टेक्स्ट मेमोरी जटिल दृश्‍य संभालती है
  • एपीआई प्रोक्शन करना - करने से पहले प्रतिक्रिया आकार के साथ परीक्षण
  • ऑफ़लाइन विकास - नेटवर्क डिपेंडेंसीज़ के बिना कार्य
  • घटना जाँच में त्रुटि - उत्पादन को तोड़ने के बिना असफल
  • सीआई/सीडी फार्मेट्स - कोई बाहरी निर्भरता का अर्थ तेजी से, अधिक भरोसेमंद निर्माण

इसके लिए कोई आदर्श नहीं:

  • उत्पाद एनवायरनमेंट - यह विकास और जांच औज़ार है
  • डीइन्टीज जांच डाटा - जब आप सटीक पुनर्भरण की जरूरत है इस्तेमाल करें
  • कम्प्लीशन जाँच - उत्पादन अनुबंध के लिए हमेशा वास्तविक एपीआईओं के खिलाफ वैध

अब आप जानते हैं कि यह कहाँ फिट है, चलो उन्नत क्षमताओं की जाँच करें.

विस्तृत विशेषताएँ

इन सुविधाओं वैकल्पिक हैं - आप केवल बुनियादी बातों से अत्यधिक मूल्य प्राप्त कर सकते हैं. लेकिन जब आपको माप पर उत्पादन की जरूरत है, ये उपकरण यहाँ हैं.

बहुल एमईएम बैकएण्ड

वेस्टर्न गाइड: बहुल एमईएम बैकएण्ड

# Fast for dev
curl http://localhost:5000/api/mock/users

# High quality for demos
curl "http://localhost:5000/api/mock/users?backend=quality"

# Cloud AI for production-like
curl "http://localhost:5000/api/mock/users?backend=openai"

सिमुलेशन सीमित करें

वेस्टर्न गाइड: पलटना व बैचिंग

जांच करें कि आपके एप्प्स दर सीमा कैसे हैंडल करता है:

{
  "EnableRateLimiting": true,
  "RateLimitDelayRange": "500-2000"
}

%d के सिमुलेशन में त्रुटि

# Test 429 rate limiting
curl "http://localhost:5000/api/mock/users?error=429&errorMessage=Rate%20limit%20exceeded"

# Test 503 unavailable
curl "http://localhost:5000/api/mock/users?error=503"

सभी 4xx तथा 5x कोड समर्थन करता है.

अनुक्रिया कैशिंग

# Generate and cache 10 variants
curl "http://localhost:5000/api/mock/users?shape={\"$cache\":10,\"id\":0,\"name\":\"string\"}"

सब्सक निवेदन तत्काल कैशेड जवाब मिलता है.

जाँचन: अधिकतरलूसी. क्लीक्समैपी. जाँच की जा रही है

पैकेज: अधिकतर सौंवेड.mockmapi. जाँच की जा रही है

सबसे ऊपर की सभी विशेषताएँ विकास के लिए महान हैं, लेकिन क्या स्वचालित परीक्षण के बारे में? HttpClient बाकी करो.

संस्थापन

dotnet add package mostlylucid.mockllmapi.Testing

मूल उपयोग

using mostlylucid.mockllmapi.Testing;

// Create a client with a single endpoint configuration
var client = HttpClientExtensions.CreateMockLlmClient(
    baseAddress: "http://localhost:5116",
    pathPattern: "/users",
    configure: endpoint => endpoint
        .WithShape(new { id = 0, name = "", email = "" })
        .WithCache(5)
);

// Make requests - configuration is automatically applied
var response = await client.GetAsync("/users");
var users = await response.Content.ReadFromJsonAsync<User[]>();

बहु अंत बिन्दुएँ

var client = HttpClientExtensions.CreateMockLlmClient(
    "http://localhost:5116",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" })
            .WithCache(10))
        .ForEndpoint("/posts", config => config
            .WithShape(new { id = 0, title = "", content = "", authorId = 0 })
            .WithCache(20))
        .ForEndpoint("/error", config => config
            .WithError(404, "Resource not found"))
);

// Each endpoint automatically uses its configuration
var usersResponse = await client.GetAsync("/users");
var postsResponse = await client.GetAsync("/posts");
var errorResponse = await client.GetAsync("/error"); // Returns 404

विन्यास विकल्प

आकार कॉन्फ़िगरेशनः

// Using anonymous objects
.WithShape(new { id = 0, name = "", active = true })

// Using JSON strings
.WithShape("{ \"id\": 0, \"name\": \"\", \"tags\": [] }")

// Complex nested structures
.WithShape(new
{
    user = new { id = 0, name = "" },
    posts = new[] { new { id = 0, title = "" } }
})

निस्पंदन निस्पादन में त्रुटि:

// Simple error
.WithError(404)

// With custom message
.WithError(404, "User not found")

// With details
.WithError(422, "Validation failed", "Email address is invalid")

स्ट्रीमिंग:

// Enable streaming with token-by-token output
.WithStreaming()
.WithSseMode("LlmTokens")

// Stream complete objects
.WithStreaming()
.WithSseMode("CompleteObjects")

// Stream array items individually
.WithStreaming()
.WithSseMode("ArrayItems")

डिपेंडेंसी इनवेशन

क़िस्म:

services.AddMockLlmHttpClient<IUserApiClient>(
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" }))
);

नामित क्लाएंट:

services.AddMockLlmHttpClient(
    name: "MockApi",
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/data", config => config
            .WithShape(new { value = 0 }))
);

// Usage
var client = httpClientFactory.CreateClient("MockApi");

एकीकरण जाँच उदाहरण

[Fact]
public async Task Should_Handle_User_Creation()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users",
        config => config
            .WithMethod("POST")
            .WithShape(new { id = 0, name = "", email = "", createdAt = "" })
    );

    // Act
    var newUser = new { name = "John Doe", email = "[email protected]" };
    var response = await client.PostAsJsonAsync("/users", newUser);

    // Assert
    response.EnsureSuccessStatusCode();
    var created = await response.Content.ReadFromJsonAsync<User>();
    Assert.NotNull(created);
    Assert.NotEqual(0, created.Id);
}

[Fact]
public async Task Should_Handle_Not_Found_Error()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users/999",
        config => config.WithError(404, "User not found")
    );

    // Act
    var response = await client.GetAsync("/users/999");

    // Assert
    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

यह कैसे कार्य करता है

वह MockLlmHttpHandler है एक DelegatingHandler कि:

  1. बाहर जाने वाले एचटीटीपी निवेदन
  2. कॉन्फ़िगर्ड अंतिमपाइंट पैटर्न के विरुद्ध मेल निवेदन
  3. क्वैरी पैरामीटर तथा एचटीटीपी शीर्ष के द्वारा उपहास कॉन्फ़िगरेशन को अनदेखा करता है
  4. सही उपहास करने के लिए परिवर्धित निवेदन को आगे बढ़ाता है

यह आपको वास्तविक उपयोग करने देता है HttpClient अपने अनुप्रयोग कोड को बदलने के बिना अपनी जांच में...

उत्तम अभ्यास व सुझाव

इस उपकरण के साथ अनेक परियोजनाओं पर काम करने के बाद, यहाँ उस पैटर्न हैं जो सबसे अच्छा काम करता है:

  1. कार्य प्रवाह के लिए हमेशा संदर्भ प्रयोग करें - बहुल चरण संचालन के दौरान सतत आईडी और डेटा सुनिश्चित करें
  2. क़िस्म सुरक्षा के लिए आकार इस्तेमाल करें - इसे आपके टाइप स्क्रिप्ट इंटरफेस से मेल बनाएँ
  3. औज़ार युक्त वास्तविक तथा ठट्ठा डाटाName - सारी दुनिया का सबसे अच्छा
  4. दायाँ मॉडल चुनें (देखें) ओसमा मॉडल्स मार्गदर्शक संपूर्ण विवरण के लिए:
    • उसी तरह, आई. वी.: ministral-3:3b (3Bbms, 32के संदर्भ) - JSON के लिए खूनी! अत्यंत तेज, अति सही, न्यूनतम रैम
    • उत्पाद- जैसा: llama3 (8Bbs, 8के संदर्भ) - उत्तम विशेषता और प्रदर्शन का सर्वोत्तम संतुलन
    • उच्च गुणवत्ता: mistral-nemo ( 12Bbs, 128के संदर्भ) - जटिल प्रसंग तथा विशाल डाटासेट्स
    • रिसोर्स- क़िस्म- अधिकारी: gemma3:4b या phi3 - हल्का विकल्प

पूर्ण दस्तावेज़ीकरण

कंटेनमेंट

फ्रन्टएण्ड विकास के लिए बैकेंड एपीआई के लिए इंतजार करने की जरूरत नहीं है. mostlylucid.mockllmapi आपको देता है:

  • कॉन्टेक्स्ट मेमोरी - लगातार, बहु- स्टेप कार्य के दौरान स्थिर डेटा प्रवाह
  • आकार नियंत्रण - अपने प्रकार के मेल खाते हैं कि स्कीमा परिभाषाओं का पालन करें
  • यूनिवर्सल प्रोटोकॉल समर्थन - RERS, ग्राफ, gRPC, सिग्नलR, SSE, ओपनपीआई
  • के-ब्रेड जाँच - उत्पन्न ठट्ठा करनेवालों के साथ वास्तविक उत्पादन डाटा मिक्स करें
  • शून्य रेस्ट - आवश्यकता बदलने पर अद्यतन करने के लिए कोई JSON भिन्न नहीं
  • जाँच की जा रही है - एकीकरण जांच के लिए छेद एपीआई

इस और पारंपरिक उपहास के बीच अंतर? आपके सामने के कार्य यथार्थवादीता से किए गए, डाटा को एक दिन से जानता है. "यह ठट्ठा डाटा के साथ काम किया लेकिन वास्तविक डेटा के साथ असफल हो गया.

आप एक सरल ब्लॉग या एक जटिल विस्तार अनुप्रयोग निर्माण कर रहे हैं, आप इसे तेजी से, अधिक अच्छी तरह से परीक्षण, और विश्वास के साथ जहाज.

शुरू करने के लिए तैयार हैं?

docker compose up -d

यही कारण है कि यह है. कोई बैकेंड जरूरी नहीं है.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.