预定义连接

使用预定义连接让用户无需重新输入认证凭据即可访问嵌入应用中的 Piece。

高级步骤如下:

  • 使用平台管理员 API 为项目创建全局连接。只有平台管理员可以编辑或删除全局连接。
  • (可选)隐藏 Piece 设置中的连接下拉菜单。

前提条件

创建预定义连接

前往**平台管理 → 安全 → API 密钥**并创建 API 密钥。保存它以便在下一步中使用。
<img src="https://mintcdn.com/activepieces/ki8mFooo8mAmhMdP/resources/screenshots/create-api-key.png?fit=max&auto=format&n=ki8mFooo8mAmhMdP&q=85&s=36a570d63af2545c8bbc4527785ac4a4" alt="创建 API 密钥" width="1420" height="900" data-path="resources/screenshots/create-api-key.png" />
在您的后端添加以下代码段,以便在每次生成 JWT 令牌时创建全局连接。
该代码段执行以下操作:

* 如果项目不存在则创建项目。
* 按照特定命名约定为项目创建全局连接。

```js theme={null}
const apiKey = 'YOUR_API_KEY';
const instanceUrl = 'https://cloud.activepieces.com';

// 您 SAAS 中用户/组织的名称
const externalProjectId = 'org_1234';
const pieceName = '@activepieces/piece-gelato';
// 这取决于您的 Piece 认证类型,可以是以下之一:['PLATFORM_OAUTH2','SECRET_TEXT','BASIC_AUTH','CUSTOM_AUTH']
const pieceAuthType = "CUSTOM_AUTH"
const connectionProps = {
    // 填写您的 Piece 认证所需的属性
}
const { id: projectId, externalId } = await getOrCreateProject({
  projectExternalId: externalProjectId,
  apiKey,
  instanceUrl,
});

await createGlobalConnection({
  projectId,
  externalProjectId,
  apiKey,
  instanceUrl,
  pieceName,
  props,
  pieceAuthType
});

```

实现代码:

```js theme={null}
async function getOrCreateProject({
    projectExternalId,
    apiKey,
    instanceUrl,
}: {
    projectExternalId: string,
    apiKey: string,
    instanceUrl: string
}): Promise<{ id: string, externalId: string }> {

    const projects = await fetch(`${instanceUrl}/api/v1/projects?externalId=${projectExternalId}`, {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
        },
    })
        .then(response => response.json())
        .then(data => data.data)
        .catch(err => {
            console.error('获取项目时出错:', err);
            return [];
        });

    if (projects.length > 0) {
        return {
            id: projects[0].id,
            externalId: projects[0].externalId
        };
    }

    const newProject = await fetch(`${instanceUrl}/api/v1/projects`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            displayName: projectExternalId,
            metadata: {},
            externalId: projectExternalId
        })
    })
        .then(response => response.json())
        .catch(err => {
            console.error('创建项目时出错:', err);
            throw err;
        });

    return {
        id: newProject.id,
        externalId: newProject.externalId
    };
} 

async function createGlobalConnection({
    projectId,
    externalProjectId,
    apiKey,
    instanceUrl,
    pieceName,
    props,
    pieceAuthType
}: {
    projectId: string,
    externalProjectId: string,
    apiKey: string,
    instanceUrl: string,
    pieceName: string,
    props: Record<string, any>,
    pieceAuthType
}) {

    const displayName = 'Gelato Connection';
    const connectionExternalId = 'gelato_' + externalProjectId;

    return fetch(`${instanceUrl}/api/v1/global-connections`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            displayName,
            pieceName,
            metadata: {},
            type: pieceAuthType,
            value: {
                type: pieceAuthType,
                props
            },
            scope: 'PLATFORM',
            projectIds: [projectId],
            externalId: connectionExternalId
        })
    });
}
```

隐藏连接下拉菜单(可选)

在调用 `createTrigger` 或 `createAction` 的地方将 `requireAuth` 设置为 `false`,这将隐藏 Builder 中 Piece 设置的连接下拉菜单。 接下来我们需要基于命名约定来获取它。 以下示例展示如何基于命名约定获取连接值,请确保创建全局连接时遵循此命名约定。
```js theme={null}
import {
   ConnectionsManager,
   Property,
   TriggerStrategy
} from "@activepieces/pieces-framework";
import {
   createTrigger
} from "@activepieces/pieces-framework";
import {
   isNil
} from "@activepieces/shared";
// 从 index.ts 文件中添加此导入,其中包含认证对象的定义。
import { auth } from '../..';

const fetchConnection = async (
	connections: ConnectionsManager,
	projectExternalId: string | undefined,
): Promise<PiecePropValueSchema<typeof auth>> => {
	if (isNil(projectExternalId)) {
		throw new Error('此项目缺少外部 ID');
	}
	// 这里的命名约定是 gelato_projectExternalId
	const connection = await connections.get(`gelato_${projectExternalId}`);
	if (isNil(connection)) {
		throw new Error(`项目 ${projectExternalId} 未找到连接`);
	}

	return connection as PiecePropValueSchema<typeof auth>;
};


export const newFlavorCreated = createTrigger({
   requireAuth: false,
   name: 'newFlavorCreated',
   displayName: '已创建新口味',
   description: '当创建新的冰淇淋口味时触发。',
   props: {
      dropdown: Property.Dropdown({
         displayName: '下拉选择',
         required: true,
         refreshers: [],
         options: async (_, {
            connections,
            project
         }) => {
            const connection = await fetchConnection(connections, (await project.externalId()));
            // 您的逻辑
            return {
               options: [{
                  label: '测试',
                  value: 'test'
               }]
            }
         }
      })
   },
   sampleData: {},
   type: TriggerStrategy.POLLING,
   async test({connections,project}) {
      const connection = await fetchConnection(connections, (await project.externalId()));
      // 使用连接执行您的逻辑
      return []
   },
   async onEnable({connections,project}) {
      const connection = await fetchConnection(connections, (await project.externalId()));
      // 使用连接执行您的逻辑
   },

   async onDisable({connections,project}) {
      const connection = await fetchConnection(connections, (await project.externalId()));
      // 使用连接执行您的逻辑
   },

   async run({connections,project}) {
    const connection = await fetchConnection(connections, (await project.externalId()));
      // 使用连接执行您的逻辑
      return []
   },
});
```