قلاب های کاربر را به یک برنامه افزودنی اضافه کنید
با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
شما می توانید به کاربرانی که برنامه افزودنی شما را نصب می کنند، این امکان را ارائه دهید که منطق سفارشی خود را در اجرای برنامه افزودنی شما وارد کنند. دو راه برای انجام این کار وجود دارد:
رویدادهای Eventarc : برای اینکه به کاربران راهی برای واکنش ناهمزمان به رویدادها بدهید، میتوانید در Eventarc منتشر کنید. کاربران می توانند توابع مدیریت رویداد را به کار گیرند که برای مثال، اعلان ها را پس از تکمیل وظایف طولانی مدت ارسال می کنند، یا می توانند عملکردهای پس از پردازش خود را تعریف کنند.
قلابهای همزمان : برای اینکه به کاربران راهی برای اضافه کردن منطق مسدود کردن به برنامه افزودنی خود بدهید، میتوانید قلابهای همزمان را در نقاط از پیش تعریفشده در عملکرد برنامه افزودنی اضافه کنید. در این نقاط، یک تابع ارائه دهنده کاربر را اجرا می کنید و تنها پس از تکمیل آن ادامه می دهید. کارهای پیش پردازش اغلب در این دسته قرار می گیرند.
یک برنامه افزودنی می تواند از یکی یا هر دو روش استفاده کند.
رویدادهای رویدادارک
برای انتشار رویدادها از یک برنامه افزودنی:
انواع رویدادهایی را که در فایل extension.yaml
منتشر خواهید کرد، اعلام کنید:
events:
- type: publisher-id.extension-name.version.event-name
description: event-description
- type: publisher-id.extension-name.version.another-event-name
description: another-event-description
شناسه type
از چندین فیلد جدا شده با نقطه ساخته شده است. فیلدهای شناسه ناشر ، نام برنامه افزودنی و نام رویداد الزامی است. فیلد نسخه توصیه می شود. برای هر نوع رویدادی که منتشر می کنید، یک نام رویداد منحصر به فرد و توصیفی انتخاب کنید.
به عنوان مثال، پسوند storage-resize-images
یک نوع رویداد واحد را اعلام می کند:
events:
- type: firebase.extensions.storage-resize-images.v1.complete
description: |
Occurs when image resizing completes. The event will contain further
details about specific formats and sizes.
کاربران می توانند هنگام نصب برنامه افزودنی انتخاب کنند که در کدام رویدادها مشترک شوند.
در توابع برنامه افزودنی خود، Eventarc API را از Admin SDK وارد کنید و یک کانال رویداد را با استفاده از تنظیمات نصب کاربر مقداردهی کنید. این تنظیمات با استفاده از متغیرهای محیطی زیر نمایش داده می شوند:
-
EVENTARC_CHANNEL
: نام کاملاً واجد شرایط کانال Eventarc که کاربر برای انتشار رویدادها انتخاب کرده است. -
EXT_SELECTED_EVENTS
: فهرستی از انواع رویداد که کاربر برای انتشار انتخاب کرده است، با کاما جدا شده است. وقتی کانالی را با این مقدار مقداردهی اولیه می کنید، Admin SDK به طور خودکار رویدادهایی را که کاربر انتخاب نکرده است فیلتر می کند. -
EVENTARC_CLOUD_EVENT_SOURCE
: شناسه منبع رویداد Cloud. Admin SDK به طور خودکار این مقدار را در قسمت source
رویدادهای منتشر شده ارسال می کند. شما معمولاً نیازی به استفاده صریح از این متغیر ندارید.
اگر رویدادها در هنگام نصب فعال نشده باشند، این متغیرها تعریف نشده خواهند بود. تنها زمانی که رویدادها فعال هستند، میتوانید از این واقعیت برای مقداردهی اولیه یک کانال رویداد استفاده کنید:
import * as admin from "firebase-admin";
import {getEventarc} from 'firebase-admin/eventarc';
admin.initializeApp();
// Set eventChannel to a newly-initialized channel, or `undefined` if events
// aren't enabled.
const eventChannel =
process.env.EVENTARC_CHANNEL &&
getEventarc().channel(process.env.EVENTARC_CHANNEL, {
allowedEventTypes: process.env.EXT_SELECTED_EVENTS,
});
رویدادها را در کانال در نقاطی در برنامه افزودنی خود که میخواهید در معرض دید کاربران قرار دهید منتشر کنید. به عنوان مثال:
// If events are enabled, publish a `complete` event to the configured
// channel.
eventChannel && eventChannel.publish({
type: 'firebase.extensions.storage-resize-images.v1.complete',
subject: filename, // the name of the original file
data: {
// ...
}
});
رویدادهایی را که منتشر میکنید، در فایل PREINSTALL یا POSTINSTALL مستند کنید.
برای هر رویداد، موارد زیر را مستند کنید:
- هدف مورد نظر آن
- نقطه در منطق برنامه افزودنی شما اجرا می شود
- داده های خروجی که شامل می شود
- شرایط اجرای آن
بهعلاوه، به کاربران هشدار دهید که در کنترلکنندههای رویداد خود اقدامی انجام ندهند که ممکن است همان برنامه افزودنی را فعال کند و در نتیجه یک حلقه بینهایت ایجاد شود.
هنگامی که رویدادها را از یک برنامه افزودنی منتشر می کنید، کاربران می توانند کنترل کننده رویداد را برای پاسخگویی با منطق سفارشی مستقر کنند.
به عنوان مثال، مثال زیر تصویر اصلی را پس از تغییر اندازه حذف می کند. توجه داشته باشید که این کنترل کننده نمونه از ویژگی subject
رویداد استفاده می کند که در این مورد نام فایل اصلی تصویر است.
exports.onimageresized = onCustomEventPublished(
"firebase.extensions.storage-resize-images.v1.complete",
(event) => {
logger.info("Received image resize completed event", event);
// For example, delete the original.
return admin.storage()
.bucket("my-project.firebasestorage.app")
.file(event.subject)
.delete();
});
برای اطلاعات بیشتر به محرک های رویداد سفارشی مراجعه کنید.
مثال
پسوند رسمی تغییر اندازه تصاویر با انتشار در Eventarc پس از تغییر اندازه یک تصویر، یک قلاب ناهمزمان را فراهم می کند.
قلاب های سنکرون
هنگامی که میخواهید قلابی را به کاربران ارائه دهید که برای عملکرد یکی از عملکردهای برنامه افزودنی باید با موفقیت کامل شود، از قلابهای همزمان استفاده کنید.
یک قلاب همزمان یک تابع ابری قابل فراخوانی HTTPS تعریف شده توسط کاربر را فراخوانی میکند و قبل از ادامه منتظر تکمیل (احتمالاً با مقدار برگشتی) است. خطا در تابع ارائه شده توسط کاربر منجر به خطا در تابع افزونه می شود.
برای آشکار کردن یک قلاب همزمان:
پارامتری را به برنامه افزودنی خود اضافه کنید که به کاربران امکان می دهد افزونه را با URL تابع Cloud سفارشی خود پیکربندی کنند. به عنوان مثال:
- param: PREPROCESSING_FUNCTION
label: Pre-processing function URL
description: >
An HTTPS callable function that will be called to transform the input data
before it is processed by this function.
type: string
example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData
required: false
در نقطه ای از برنامه افزودنی خود که می خواهید قلاب را در معرض نمایش قرار دهید، تابع را با استفاده از URL آن فراخوانی کنید. به عنوان مثال:
const functions = require('firebase-functions/v1');
const fetch = require('node-fetch');
const preprocessFunctionURL = process.env.PREPROCESSING_FUNCTION;
exports.yourFunctionName = functions.firestore.document("collection/{doc_id}")
.onWrite((change, context) => {
// PREPROCESSING_FUNCTION hook begins here.
// If a preprocessing function is defined, call it before continuing.
if (preprocessFunctionURL) {
try {
await fetch(preprocessFunctionURL); // Could also be a POST request if you want to send data.
} catch (e) {
// Preprocessing failure causes the function to fail.
functions.logger.error("Preprocessor error:", e);
return;
}
}
// End of PREPROCESSING_FUNCTION hook.
// Main function logic follows.
// ...
});
قلاب هایی را که در دسترس می گذارید در فایل PREINSTALL یا POSTINSTALL مستند کنید.
برای هر قلاب، موارد زیر را مستند کنید:
- هدف مورد نظر آن
- نقطه در منطق برنامه افزودنی شما اجرا می شود
- ورودی ها و خروجی های مورد انتظار آن
- شرایط (یا گزینه های) برای اجرای آن
بهعلاوه، به کاربران هشدار دهید که هیچگونه عملی را در عملکرد هوک انجام ندهند که ممکن است همان پسوند را فعال کند و در نتیجه یک حلقه نامحدود ایجاد شود.
مثال
پسوند Algolia Search یک قلاب همزمان برای فراخوانی یک تابع تبدیل ارائه شده توسط کاربر قبل از نوشتن در Algolia فراهم می کند.
جز در مواردی که غیر از این ذکر شده باشد،محتوای این صفحه تحت مجوز Creative Commons Attribution 4.0 License است. نمونه کدها نیز دارای مجوز Apache 2.0 License است. برای اطلاع از جزئیات، به خطمشیهای سایت Google Developers مراجعه کنید. جاوا علامت تجاری ثبتشده Oracle و/یا شرکتهای وابسته به آن است.
تاریخ آخرین بهروزرسانی 2025-07-25 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-07-25 بهوقت ساعت هماهنگ جهانی."],[],[],null,["\u003cbr /\u003e\n\nYou can provide users who install your extension the ability to insert their own\ncustom logic into the execution of your extension. There are two ways to\naccomplish this:\n\n- **Eventarc events**: to give users a way to asynchronously react to\n events, you can publish to Eventarc. Users can deploy event handler\n functions that, for example, send notifications after long-running\n tasks complete, or they can define their own post-processing functions.\n\n- **Synchronous hooks**: to give users a way to add blocking logic to your\n extension, you can add synchronous hooks at predefined points in the\n extension's operation. At these points, you run a user-provider function\n and proceed only after it completes. Pre-processing tasks often fall under\n this category.\n\nAn extension can use either or both methods.\n\nEventarc events\n\nTo publish events from an extension:\n\n1. Declare the event types you will publish in the `extension.yaml` file:\n\n events:\n - type: publisher-id.extension-name.version.event-name\n description: event-description\n - type: publisher-id.extension-name.version.another-event-name\n description: another-event-description\n\n The `type` identifier is made of several dot-delimited fields. The\n [publisher ID](/docs/extensions/publishers/register), extension name, and event name fields are\n required. The version field is recommended. Choose a unique and descriptive\n event name for each event type you publish.\n\n For example, the [`storage-resize-images` extension](https://github.com/firebase/extensions/blob/next/storage-resize-images/extension.yaml)\n declares a single event type: \n\n events:\n - type: firebase.extensions.storage-resize-images.v1.complete\n description: |\n Occurs when image resizing completes. The event will contain further\n details about specific formats and sizes.\n\n Users will be able to choose which events to subscribe to when they\n install the extension.\n2. In your extension functions, import the Eventarc API from the Admin SDK\n and initialize an event channel using the user's installation settings.\n These settings are exposed using the following environment variables:\n\n - `EVENTARC_CHANNEL`: the fully-qualified name of the Eventarc channel to which the user chose to publish events.\n - `EXT_SELECTED_EVENTS`: a comma-separated list of event types the user chose to publish. When you initialize a channel with this value, the Admin SDK automatically filters out events user did not select.\n - `EVENTARC_CLOUD_EVENT_SOURCE`: the Cloud Event source identifier. The Admin SDK automatically passes this value in the `source` field of published events. You typically don't need to explicitly use this variable.\n\n If events weren't enabled at installation, these variables will be\n undefined. You can use this fact to initialize an event channel only when\n events are enabled: \n\n import * as admin from \"firebase-admin\";\n import {getEventarc} from 'firebase-admin/eventarc';\n\n admin.initializeApp();\n\n // Set eventChannel to a newly-initialized channel, or `undefined` if events\n // aren't enabled.\n const eventChannel =\n process.env.EVENTARC_CHANNEL &&\n getEventarc().channel(process.env.EVENTARC_CHANNEL, {\n allowedEventTypes: process.env.EXT_SELECTED_EVENTS,\n });\n\n3. Publish events to the channel at the points in your extension you want to\n expose to users. For example:\n\n // If events are enabled, publish a `complete` event to the configured\n // channel.\n eventChannel && eventChannel.publish({\n type: 'firebase.extensions.storage-resize-images.v1.complete',\n subject: filename, // the name of the original file\n data: {\n // ...\n }\n });\n\n4. Document the events you publish, in either the PREINSTALL or POSTINSTALL\n file.\n\n For each event, document the following:\n - Its intended purpose\n - The point in your extension's logic it runs\n - The output data it includes\n - The conditions for its execution\n\n Additionally, warn users not to perform any actions in their event\n handlers that might trigger the same extension, resulting in an infinite\n loop.\n\nWhen you publish events from an extension, users can deploy event handlers\nto respond with custom logic.\n\nFor example, the following example deletes the original image after it has been\nresized. Note that this example handler makes use of the `subject` property of\nthe event, which in this case is the image's original filename. \n\n exports.onimageresized = onCustomEventPublished(\n \"firebase.extensions.storage-resize-images.v1.complete\",\n (event) =\u003e {\n logger.info(\"Received image resize completed event\", event);\n // For example, delete the original.\n return admin.storage()\n .bucket(\"my-project.firebasestorage.app\")\n .file(event.subject)\n .delete();\n });\n\nSee [Custom event triggers](/docs/functions/custom-events#handle-events) for more\ninformation.\n\nExample\n\nThe official [Resize Images extension](https://github.com/firebase/extensions/tree/next/storage-resize-images)\nprovides an asynchronous hook by [publishing to Eventarc](https://github.com/firebase/extensions/blob/c29781c7e67c004e2491e4ce3c43b25b05bd3de6/storage-resize-images/functions/src/index.ts#L109-L117)\nafter resizing an image.\n\nSynchronous hooks\n\nWhen you want to provide users with a hook that must complete successfully\nfor one of your extension functions to operate, use *synchronous hooks*.\n\nA synchronous hook calls a user-defined [HTTPS callable Cloud\nFunction](/docs/functions/http-events) and awaits completion (possibly with a\nreturned value) before continuing. An error in the user-provided function\nresults in an error in the extension function.\n\nTo expose a synchronous hook:\n\n1. Add a parameter to your extension that allows users to configure the\n extension with the URL to their custom Cloud Function. For example:\n\n - param: PREPROCESSING_FUNCTION\n label: Pre-processing function URL\n description: \u003e\n An HTTPS callable function that will be called to transform the input data\n before it is processed by this function.\n type: string\n example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData\n required: false\n\n2. At the point in your extension where you want to expose the hook, call the\n function using its URL. For example:\n\n const functions = require('firebase-functions/v1');\n const fetch = require('node-fetch');\n\n const preprocessFunctionURL = process.env.PREPROCESSING_FUNCTION;\n\n exports.yourFunctionName = functions.firestore.document(\"collection/{doc_id}\")\n .onWrite((change, context) =\u003e {\n // PREPROCESSING_FUNCTION hook begins here.\n // If a preprocessing function is defined, call it before continuing.\n if (preprocessFunctionURL) {\n try {\n await fetch(preprocessFunctionURL); // Could also be a POST request if you want to send data.\n } catch (e) {\n // Preprocessing failure causes the function to fail.\n functions.logger.error(\"Preprocessor error:\", e);\n return;\n }\n }\n // End of PREPROCESSING_FUNCTION hook.\n\n // Main function logic follows.\n // ...\n });\n\n3. Document any hooks you make available in either the PREINSTALL or\n POSTINSTALL file.\n\n For each hook, document the following:\n - Its intended purpose\n - The point in your extension's logic it runs\n - Its expected inputs and outputs\n - The conditions (or options) for its execution\n\n Additionally, warn users not to perform any actions in the hook\n function that might trigger the same extension, resulting in an infinite\n loop.\n\nExample\n\nThe [Algolia Search extension](https://github.com/algolia/firestore-algolia-search/)\nprovides a synchronous hook to [call a user-supplied transform function](https://github.com/algolia/firestore-algolia-search/blob/34592d513eac22691d76917874a6466032976f67/functions/src/transform.ts)\nprior to writing to Algolia."]]