好的, 让我们来详细规划第 11 部分: 扩展和集成。我们将这部分分为 3 天, 每天专注于特定的扩展和集成任务。
第 11 部分:扩展和集成 (3 天)
Day 1: 开发浏览器扩展
-
设置浏览器扩展项目结构 创建新的目录
browser-extension并初始化:mkdir browser-extension cd browser-extension npm init -y npm install --save-dev webpack webpack-cli copy-webpack-plugin -
创建 manifest 文件 在
browser-extension目录下创建manifest.json:{ "manifest_version": 2, "name": "LightweightTodo Pro Extension", "version": "1.0", "description": "Quickly add todos from any webpage", "permissions": ["activeTab", "storage"], "browser_action": { "default_popup": "popup.html", "default_icon": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" } }, "icons": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" } } -
创建 popup 界面 在
browser-extension目录下创建popup.html:<!DOCTYPE html> <html> <head> <title>Add Todo</title> </head> <body> <form id="addTodoForm"> <input type="text" id="todoTitle" placeholder="Todo title" required> <textarea id="todoDescription" placeholder="Description"></textarea> <button type="submit">Add Todo</button> </form> <script src="popup.js"></script> </body> </html> -
实现 popup 逻辑 创建
browser-extension/src/popup.ts:document.addEventListener('DOMContentLoaded', () => { const form = document.getElementById('addTodoForm') as HTMLFormElement; const titleInput = document.getElementById('todoTitle') as HTMLInputElement; const descriptionInput = document.getElementById('todoDescription') as HTMLTextAreaElement; form.addEventListener('submit', async (e) => { e.preventDefault(); const title = titleInput.value; const description = descriptionInput.value; try { const response = await fetch('https://api.lightweighttodo.com/todos', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('token') }, body: JSON.stringify({ title, description }) }); if (response.ok) { alert('Todo added successfully!'); titleInput.value = ''; descriptionInput.value = ''; } else { throw new Error('Failed to add todo'); } } catch (error) { alert('Error: ' + error.message); } }); }); -
配置 webpack 创建
browser-extension/webpack.config.js:const path = require('path'); const CopyPlugin = require('copy-webpack-plugin'); module.exports = { entry: './src/popup.ts', output: { filename: 'popup.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.ts$/, use: 'ts-loader', exclude: /node_modules/, }, ], }, resolve: { extensions: ['.ts', '.js'], }, plugins: [ new CopyPlugin({ patterns: [ { from: 'manifest.json', to: 'manifest.json' }, { from: 'popup.html', to: 'popup.html' }, { from: 'icons', to: 'icons' }, ], }), ], };
Day 2: 开发公共 API
-
设计 API 端点 创建
api-design.md:# LightweightTodo Pro Public API Base URL: https://api.lightweighttodo.com/v1 ## Authentication All requests must include an `Authorization` header with a valid API key. ## Endpoints ### List Todos GET /todos Query Parameters: - status: 'all' | 'active' | 'completed' - page: number - limit: number ### Get Todo GET /todos/:id ### Create Todo POST /todos Request Body: { "title": string, "description": string, "dueDate": string (ISO 8601 format), "tags": string[] } ### Update Todo PUT /todos/:id Request Body: { "title": string, "description": string, "dueDate": string (ISO 8601 format), "tags": string[], "status": 'active' | 'completed' } ### Delete Todo DELETE /todos/:id ### List Tags GET /tags ### Create Tag POST /tags Request Body: { "name": string } ### Delete Tag DELETE /tags/:id -
实现 API 端点 在后端项目中创建新的控制器
PublicApiController.ts:import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards } from '@nestjs/common'; import { ApiKeyGuard } from '../guards/api-key.guard'; import { TodoService } from '../services/todo.service'; import { TagService } from '../services/tag.service'; @Controller('v1') @UseGuards(ApiKeyGuard) export class PublicApiController { constructor( private readonly todoService: TodoService, private readonly tagService: TagService ) {} @Get('todos') async listTodos(@Query() query) { return this.todoService.list(query); } @Get('todos/:id') async getTodo(@Param('id') id: string) { return this.todoService.get(id); } @Post('todos') async createTodo(@Body() todoData) { return this.todoService.create(todoData); } @Put('todos/:id') async updateTodo(@Param('id') id: string, @Body() todoData) { return this.todoService.update(id, todoData); } @Delete('todos/:id') async deleteTodo(@Param('id') id: string) { return this.todoService.delete(id); } @Get('tags') async listTags() { return this.tagService.list(); } @Post('tags') async createTag(@Body() tagData) { return this.tagService.create(tagData); } @Delete('tags/:id') async deleteTag(@Param('id') id: string) { return this.tagService.delete(id); } } -
实现 API 密钥认证 创建
src/guards/api-key.guard.ts:import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common'; import { Observable } from 'rxjs'; @Injectable() export class ApiKeyGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { const request = context.switchToHttp().getRequest(); const apiKey = request.get('Authorization'); if (!apiKey) { throw new UnauthorizedException('API key is missing'); } // In a real application, you would validate the API key against a database if (apiKey !== 'valid-api-key') { throw new UnauthorizedException('Invalid API key'); } return true; } } -
编写 API 文档 使用 Swagger 生成 API 文档。安装所需依赖:
npm install --save @nestjs/swagger swagger-ui-express在
main.ts中设置 Swagger:import { NestFactory } from '@nestjs/core'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const config = new DocumentBuilder() .setTitle('LightweightTodo Pro API') .setDescription('The LightweightTodo Pro API description') .setVersion('1.0') .addApiKey({ type: 'apiKey', name: 'Authorization', in: 'header' }, 'API-Key') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); await app.listen(3000); } bootstrap();
Day 3: 集成第三方服务
-
集成 Google Calendar 安装所需依赖:
npm install googleapis创建
src/services/google-calendar.service.ts:import { Injectable } from '@nestjs/common'; import { google } from 'googleapis'; @Injectable() export class GoogleCalendarService { private calendar; constructor() { const auth = new google.auth.JWT( process.env.GOOGLE_CLIENT_EMAIL, null, process.env.GOOGLE_PRIVATE_KEY, ['https://www.googleapis.com/auth/calendar'] ); this.calendar = google.calendar({ version: 'v3', auth }); } async addEvent(todo) { const event = { summary: todo.title, description: todo.description, start: { dateTime: todo.dueDate, timeZone: 'UTC', }, end: { dateTime: todo.dueDate, timeZone: 'UTC', }, }; try { const response = await this.calendar.events.insert({ calendarId: 'primary', resource: event, }); return response.data; } catch (error) { console.error('Error adding event to Google Calendar:', error); throw error; } } } -
集成 Slack 通知 安装所需依赖:
npm install @slack/web-api创建
src/services/slack.service.ts:import { Injectable } from '@nestjs/common'; import { WebClient } from '@slack/web-api'; @Injectable() export class SlackService { private slack: WebClient; constructor() { this.slack = new WebClient(process.env.SLACK_BOT_TOKEN); } async sendNotification(message: string) { try { await this.slack.chat.postMessage({ channel: process.env.SLACK_CHANNEL_ID, text: message, }); } catch (error) { console.error('Error sending Slack notification:', error); throw error; } } } -
实现集成逻辑 更新
TodoService以使用新的集成服务:import { Injectable } from '@nestjs/common'; import { GoogleCalendarService } from './google-calendar.service'; import { SlackService } from './slack.service'; @Injectable() export class TodoService { constructor( private readonly googleCalendarService: GoogleCalendarService, private readonly slackService: SlackService ) {} async create(todoData) { // 创建todo的逻辑... // 添加到Google Calendar await this.googleCalendarService.addEvent(createdTodo); // 发送Slack通知 await this.slackService.sendNotification(`New todo created: ${createdTodo.title}`); return createdTodo; } // 其他方法... } -
配置环境变量 更新
.env文件:GOOGLE_CLIENT_EMAIL=your-google-client-email GOOGLE_PRIVATE_KEY=your-google-private-key SLACK_BOT_TOKEN=your-slack-bot-token SLACK_CHANNEL_ID=your-slack-channel-id -
更新文档 在
README.md中添加新的集成信息:## Integrations ### Google Calendar LightweightTodo Pro now integrates with Google Calendar. When you create a todo with a due date, it will automatically be added to your Google Calendar. ### Slack Notifications Receive Slack notifications for important todo updates. Configure your Slack workspace and channel in the settings to enable this feature. ## API LightweightTodo Pro now offers a public API for developers. Check out our [API documentation](api-docs.md) for more information on how to integrate LightweightTodo Pro into your own applications.
这个详细计划涵盖了第 11 部分的扩展和集成, 包括开发浏览器扩展、创建公共 API, 以及集成第三方服务如 Google Calendar 和 Slack。通过这些步骤, LightweightTodo Pro 的功能得到了显著扩展, 为用户提供了更多的使用方式和集成选项。