@patricio0312rev/skillset 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +176 -0
  4. package/bin/cli.js +37 -0
  5. package/package.json +55 -0
  6. package/src/commands/init.js +301 -0
  7. package/src/index.js +168 -0
  8. package/src/lib/config.js +200 -0
  9. package/src/lib/generator.js +166 -0
  10. package/src/utils/display.js +95 -0
  11. package/src/utils/readme.js +196 -0
  12. package/src/utils/tool-specific.js +233 -0
  13. package/templates/ai-engineering/agent-orchestration-planner/ SKILL.md +266 -0
  14. package/templates/ai-engineering/cost-latency-optimizer/ SKILL.md +270 -0
  15. package/templates/ai-engineering/doc-to-vector-dataset-generator/ SKILL.md +239 -0
  16. package/templates/ai-engineering/evaluation-harness/ SKILL.md +219 -0
  17. package/templates/ai-engineering/guardrails-safety-filter-builder/ SKILL.md +226 -0
  18. package/templates/ai-engineering/llm-debugger/ SKILL.md +283 -0
  19. package/templates/ai-engineering/prompt-regression-tester/ SKILL.md +216 -0
  20. package/templates/ai-engineering/prompt-template-builder/ SKILL.md +393 -0
  21. package/templates/ai-engineering/rag-pipeline-builder/ SKILL.md +244 -0
  22. package/templates/ai-engineering/tool-function-schema-designer/ SKILL.md +219 -0
  23. package/templates/architecture/adr-writer/ SKILL.md +250 -0
  24. package/templates/architecture/api-versioning-deprecation-planner/ SKILL.md +331 -0
  25. package/templates/architecture/domain-model-boundaries-mapper/ SKILL.md +300 -0
  26. package/templates/architecture/migration-planner/ SKILL.md +376 -0
  27. package/templates/architecture/performance-budget-setter/ SKILL.md +318 -0
  28. package/templates/architecture/reliability-strategy-builder/ SKILL.md +286 -0
  29. package/templates/architecture/rfc-generator/ SKILL.md +362 -0
  30. package/templates/architecture/scalability-playbook/ SKILL.md +279 -0
  31. package/templates/architecture/system-design-generator/ SKILL.md +339 -0
  32. package/templates/architecture/tech-debt-prioritizer/ SKILL.md +329 -0
  33. package/templates/backend/api-contract-normalizer/ SKILL.md +487 -0
  34. package/templates/backend/api-endpoint-generator/ SKILL.md +415 -0
  35. package/templates/backend/auth-module-builder/ SKILL.md +99 -0
  36. package/templates/backend/background-jobs-designer/ SKILL.md +166 -0
  37. package/templates/backend/caching-strategist/ SKILL.md +190 -0
  38. package/templates/backend/error-handling-standardizer/ SKILL.md +174 -0
  39. package/templates/backend/rate-limiting-abuse-protection/ SKILL.md +147 -0
  40. package/templates/backend/rbac-permissions-builder/ SKILL.md +158 -0
  41. package/templates/backend/service-layer-extractor/ SKILL.md +269 -0
  42. package/templates/backend/webhook-receiver-hardener/ SKILL.md +211 -0
  43. package/templates/ci-cd/artifact-sbom-publisher/ SKILL.md +236 -0
  44. package/templates/ci-cd/caching-strategy-optimizer/ SKILL.md +195 -0
  45. package/templates/ci-cd/deployment-checklist-generator/ SKILL.md +381 -0
  46. package/templates/ci-cd/github-actions-pipeline-creator/ SKILL.md +348 -0
  47. package/templates/ci-cd/monorepo-ci-optimizer/ SKILL.md +298 -0
  48. package/templates/ci-cd/preview-environments-builder/ SKILL.md +187 -0
  49. package/templates/ci-cd/quality-gates-enforcer/ SKILL.md +342 -0
  50. package/templates/ci-cd/release-automation-builder/ SKILL.md +281 -0
  51. package/templates/ci-cd/rollback-workflow-builder/ SKILL.md +372 -0
  52. package/templates/ci-cd/secrets-env-manager/ SKILL.md +242 -0
  53. package/templates/db-management/backup-restore-runbook-generator/ SKILL.md +505 -0
  54. package/templates/db-management/data-integrity-auditor/ SKILL.md +505 -0
  55. package/templates/db-management/data-retention-archiving-planner/ SKILL.md +430 -0
  56. package/templates/db-management/data-seeding-fixtures-builder/ SKILL.md +375 -0
  57. package/templates/db-management/db-performance-watchlist/ SKILL.md +425 -0
  58. package/templates/db-management/etl-sync-job-builder/ SKILL.md +457 -0
  59. package/templates/db-management/multi-tenant-safety-checker/ SKILL.md +398 -0
  60. package/templates/db-management/prisma-migration-assistant/ SKILL.md +379 -0
  61. package/templates/db-management/schema-consistency-checker/ SKILL.md +440 -0
  62. package/templates/db-management/sql-query-optimizer/ SKILL.md +324 -0
  63. package/templates/foundation/changelog-writer/ SKILL.md +431 -0
  64. package/templates/foundation/code-formatter-installer/ SKILL.md +320 -0
  65. package/templates/foundation/codebase-summarizer/ SKILL.md +360 -0
  66. package/templates/foundation/dependency-doctor/ SKILL.md +163 -0
  67. package/templates/foundation/dev-environment-bootstrapper/ SKILL.md +259 -0
  68. package/templates/foundation/dev-onboarding-builder/ SKILL.md +556 -0
  69. package/templates/foundation/docs-starter-kit/ SKILL.md +574 -0
  70. package/templates/foundation/explaining-code/SKILL.md +13 -0
  71. package/templates/foundation/git-hygiene-enforcer/ SKILL.md +455 -0
  72. package/templates/foundation/project-scaffolder/ SKILL.md +65 -0
  73. package/templates/foundation/project-scaffolder/references/templates.md +126 -0
  74. package/templates/foundation/repo-structure-linter/ SKILL.md +0 -0
  75. package/templates/foundation/repo-structure-linter/references/conventions.md +98 -0
  76. package/templates/frontend/animation-micro-interaction-pack/ SKILL.md +41 -0
  77. package/templates/frontend/component-scaffold-generator/ SKILL.md +562 -0
  78. package/templates/frontend/design-to-component-translator/ SKILL.md +547 -0
  79. package/templates/frontend/form-wizard-builder/ SKILL.md +553 -0
  80. package/templates/frontend/frontend-refactor-planner/ SKILL.md +37 -0
  81. package/templates/frontend/i18n-frontend-implementer/ SKILL.md +44 -0
  82. package/templates/frontend/modal-drawer-system/ SKILL.md +377 -0
  83. package/templates/frontend/page-layout-builder/ SKILL.md +630 -0
  84. package/templates/frontend/state-ux-flow-builder/ SKILL.md +23 -0
  85. package/templates/frontend/table-builder/ SKILL.md +350 -0
  86. package/templates/performance/alerting-dashboard-builder/ SKILL.md +162 -0
  87. package/templates/performance/backend-latency-profiler-helper/ SKILL.md +108 -0
  88. package/templates/performance/caching-cdn-strategy-planner/ SKILL.md +150 -0
  89. package/templates/performance/capacity-planning-helper/ SKILL.md +242 -0
  90. package/templates/performance/core-web-vitals-tuner/ SKILL.md +126 -0
  91. package/templates/performance/incident-runbook-generator/ SKILL.md +162 -0
  92. package/templates/performance/load-test-scenario-builder/ SKILL.md +256 -0
  93. package/templates/performance/observability-setup/ SKILL.md +232 -0
  94. package/templates/performance/postmortem-writer/ SKILL.md +203 -0
  95. package/templates/performance/structured-logging-standardizer/ SKILL.md +122 -0
  96. package/templates/security/auth-security-reviewer/ SKILL.md +428 -0
  97. package/templates/security/dependency-vulnerability-triage/ SKILL.md +495 -0
  98. package/templates/security/input-validation-sanitization-auditor/ SKILL.md +76 -0
  99. package/templates/security/pii-redaction-logging-policy-builder/ SKILL.md +65 -0
  100. package/templates/security/rbac-policy-tester/ SKILL.md +80 -0
  101. package/templates/security/secrets-scanner/ SKILL.md +462 -0
  102. package/templates/security/secure-headers-csp-builder/ SKILL.md +404 -0
  103. package/templates/security/security-incident-playbook-generator/ SKILL.md +76 -0
  104. package/templates/security/security-pr-checklist-skill/ SKILL.md +62 -0
  105. package/templates/security/threat-model-generator/ SKILL.md +394 -0
  106. package/templates/testing/contract-testing-builder/ SKILL.md +492 -0
  107. package/templates/testing/coverage-strategist/ SKILL.md +436 -0
  108. package/templates/testing/e2e-test-builder/ SKILL.md +382 -0
  109. package/templates/testing/flaky-test-detective/ SKILL.md +416 -0
  110. package/templates/testing/integration-test-builder/ SKILL.md +525 -0
  111. package/templates/testing/mocking-assistant/ SKILL.md +383 -0
  112. package/templates/testing/snapshot-test-refactorer/ SKILL.md +375 -0
  113. package/templates/testing/test-data-factory-builder/ SKILL.md +449 -0
  114. package/templates/testing/test-reporting-triage-skill/ SKILL.md +469 -0
  115. package/templates/testing/unit-test-generator/ SKILL.md +548 -0
@@ -0,0 +1,487 @@
1
+ ---
2
+ name: api-endpoint-generator
3
+ description: Generates CRUD REST API endpoints with request validation, TypeScript types, consistent response formats, error handling, and documentation. Includes route handlers, validation schemas (Zod/Joi), typed responses, and usage examples. Use when building "REST API", "CRUD endpoints", "API routes", or "backend endpoints".
4
+ ---
5
+
6
+ # API Endpoint Generator
7
+
8
+ Generate production-ready CRUD API endpoints with validation and type safety.
9
+
10
+ ## Core Workflow
11
+
12
+ 1. **Define resource**: Entity name and schema
13
+ 2. **Generate routes**: POST, GET, PUT/PATCH, DELETE endpoints
14
+ 3. **Add validation**: Request body/query validation with Zod/Joi
15
+ 4. **Type responses**: TypeScript interfaces for all responses
16
+ 5. **Error handling**: Consistent error responses
17
+ 6. **Documentation**: OpenAPI/Swagger specs
18
+ 7. **Examples**: Request/response samples
19
+
20
+ ## Express + TypeScript Pattern
21
+
22
+ ```typescript
23
+ // types/user.types.ts
24
+ export interface User {
25
+ id: string;
26
+ email: string;
27
+ name: string;
28
+ role: "user" | "admin";
29
+ createdAt: Date;
30
+ updatedAt: Date;
31
+ }
32
+
33
+ export interface CreateUserDto {
34
+ email: string;
35
+ name: string;
36
+ password: string;
37
+ }
38
+
39
+ export interface UpdateUserDto {
40
+ name?: string;
41
+ email?: string;
42
+ }
43
+
44
+ export interface ApiResponse<T> {
45
+ success: boolean;
46
+ data?: T;
47
+ error?: ApiError;
48
+ meta?: PaginationMeta;
49
+ }
50
+
51
+ export interface ApiError {
52
+ code: string;
53
+ message: string;
54
+ details?: Record<string, string[]>;
55
+ }
56
+ ```
57
+
58
+ ## Validation Schemas (Zod)
59
+
60
+ ```typescript
61
+ // schemas/user.schema.ts
62
+ import { z } from "zod";
63
+
64
+ export const createUserSchema = z.object({
65
+ email: z.string().email("Invalid email address"),
66
+ name: z.string().min(2, "Name must be at least 2 characters"),
67
+ password: z
68
+ .string()
69
+ .min(8, "Password must be at least 8 characters")
70
+ .regex(/[A-Z]/, "Password must contain uppercase letter")
71
+ .regex(/[0-9]/, "Password must contain number"),
72
+ });
73
+
74
+ export const updateUserSchema = z
75
+ .object({
76
+ name: z.string().min(2).optional(),
77
+ email: z.string().email().optional(),
78
+ })
79
+ .refine((data) => Object.keys(data).length > 0, {
80
+ message: "At least one field must be provided",
81
+ });
82
+
83
+ export const getUsersQuerySchema = z.object({
84
+ page: z.coerce.number().int().positive().default(1),
85
+ limit: z.coerce.number().int().min(1).max(100).default(10),
86
+ sortBy: z.enum(["name", "email", "createdAt"]).optional(),
87
+ sortOrder: z.enum(["asc", "desc"]).default("desc"),
88
+ search: z.string().optional(),
89
+ });
90
+
91
+ export type CreateUserDto = z.infer<typeof createUserSchema>;
92
+ export type UpdateUserDto = z.infer<typeof updateUserSchema>;
93
+ export type GetUsersQuery = z.infer<typeof getUsersQuerySchema>;
94
+ ```
95
+
96
+ ## CRUD Route Handlers
97
+
98
+ ```typescript
99
+ // routes/users.routes.ts
100
+ import { Router } from "express";
101
+ import { UserController } from "../controllers/user.controller";
102
+ import { validateRequest } from "../middleware/validate";
103
+ import { authenticate } from "../middleware/auth";
104
+ import {
105
+ createUserSchema,
106
+ updateUserSchema,
107
+ getUsersQuerySchema,
108
+ } from "../schemas/user.schema";
109
+
110
+ const router = Router();
111
+ const controller = new UserController();
112
+
113
+ // Create
114
+ router.post(
115
+ "/",
116
+ authenticate,
117
+ validateRequest({ body: createUserSchema }),
118
+ controller.create
119
+ );
120
+
121
+ // Read (list)
122
+ router.get(
123
+ "/",
124
+ authenticate,
125
+ validateRequest({ query: getUsersQuerySchema }),
126
+ controller.list
127
+ );
128
+
129
+ // Read (single)
130
+ router.get("/:id", authenticate, controller.getById);
131
+
132
+ // Update
133
+ router.patch(
134
+ "/:id",
135
+ authenticate,
136
+ validateRequest({ body: updateUserSchema }),
137
+ controller.update
138
+ );
139
+
140
+ // Delete
141
+ router.delete("/:id", authenticate, controller.delete);
142
+
143
+ export default router;
144
+ ```
145
+
146
+ ## Controller Implementation
147
+
148
+ ```typescript
149
+ // controllers/user.controller.ts
150
+ import { Request, Response, NextFunction } from "express";
151
+ import { UserService } from "../services/user.service";
152
+ import {
153
+ CreateUserDto,
154
+ UpdateUserDto,
155
+ GetUsersQuery,
156
+ } from "../types/user.types";
157
+ import { ApiResponse } from "../types/api.types";
158
+
159
+ export class UserController {
160
+ private service = new UserService();
161
+
162
+ create = async (
163
+ req: Request<{}, {}, CreateUserDto>,
164
+ res: Response<ApiResponse<User>>,
165
+ next: NextFunction
166
+ ) => {
167
+ try {
168
+ const user = await this.service.create(req.body);
169
+ res.status(201).json({
170
+ success: true,
171
+ data: user,
172
+ });
173
+ } catch (error) {
174
+ next(error);
175
+ }
176
+ };
177
+
178
+ list = async (
179
+ req: Request<{}, {}, {}, GetUsersQuery>,
180
+ res: Response<ApiResponse<User[]>>,
181
+ next: NextFunction
182
+ ) => {
183
+ try {
184
+ const { page, limit, sortBy, sortOrder, search } = req.query;
185
+ const result = await this.service.findAll({
186
+ page,
187
+ limit,
188
+ sortBy,
189
+ sortOrder,
190
+ search,
191
+ });
192
+
193
+ res.json({
194
+ success: true,
195
+ data: result.users,
196
+ meta: {
197
+ page: result.page,
198
+ limit: result.limit,
199
+ total: result.total,
200
+ totalPages: result.totalPages,
201
+ },
202
+ });
203
+ } catch (error) {
204
+ next(error);
205
+ }
206
+ };
207
+
208
+ getById = async (
209
+ req: Request<{ id: string }>,
210
+ res: Response<ApiResponse<User>>,
211
+ next: NextFunction
212
+ ) => {
213
+ try {
214
+ const user = await this.service.findById(req.params.id);
215
+ if (!user) {
216
+ return res.status(404).json({
217
+ success: false,
218
+ error: {
219
+ code: "USER_NOT_FOUND",
220
+ message: "User not found",
221
+ },
222
+ });
223
+ }
224
+ res.json({
225
+ success: true,
226
+ data: user,
227
+ });
228
+ } catch (error) {
229
+ next(error);
230
+ }
231
+ };
232
+
233
+ update = async (
234
+ req: Request<{ id: string }, {}, UpdateUserDto>,
235
+ res: Response<ApiResponse<User>>,
236
+ next: NextFunction
237
+ ) => {
238
+ try {
239
+ const user = await this.service.update(req.params.id, req.body);
240
+ if (!user) {
241
+ return res.status(404).json({
242
+ success: false,
243
+ error: {
244
+ code: "USER_NOT_FOUND",
245
+ message: "User not found",
246
+ },
247
+ });
248
+ }
249
+ res.json({
250
+ success: true,
251
+ data: user,
252
+ });
253
+ } catch (error) {
254
+ next(error);
255
+ }
256
+ };
257
+
258
+ delete = async (
259
+ req: Request<{ id: string }>,
260
+ res: Response<ApiResponse<void>>,
261
+ next: NextFunction
262
+ ) => {
263
+ try {
264
+ const deleted = await this.service.delete(req.params.id);
265
+ if (!deleted) {
266
+ return res.status(404).json({
267
+ success: false,
268
+ error: {
269
+ code: "USER_NOT_FOUND",
270
+ message: "User not found",
271
+ },
272
+ });
273
+ }
274
+ res.status(204).send();
275
+ } catch (error) {
276
+ next(error);
277
+ }
278
+ };
279
+ }
280
+ ```
281
+
282
+ ## Validation Middleware
283
+
284
+ ```typescript
285
+ // middleware/validate.ts
286
+ import { Request, Response, NextFunction } from "express";
287
+ import { ZodSchema } from "zod";
288
+
289
+ interface ValidationSchemas {
290
+ body?: ZodSchema;
291
+ query?: ZodSchema;
292
+ params?: ZodSchema;
293
+ }
294
+
295
+ export const validateRequest = (schemas: ValidationSchemas) => {
296
+ return (req: Request, res: Response, next: NextFunction) => {
297
+ try {
298
+ if (schemas.body) {
299
+ req.body = schemas.body.parse(req.body);
300
+ }
301
+ if (schemas.query) {
302
+ req.query = schemas.query.parse(req.query);
303
+ }
304
+ if (schemas.params) {
305
+ req.params = schemas.params.parse(req.params);
306
+ }
307
+ next();
308
+ } catch (error) {
309
+ if (error instanceof z.ZodError) {
310
+ return res.status(400).json({
311
+ success: false,
312
+ error: {
313
+ code: "VALIDATION_ERROR",
314
+ message: "Invalid request data",
315
+ details: error.flatten().fieldErrors,
316
+ },
317
+ });
318
+ }
319
+ next(error);
320
+ }
321
+ };
322
+ };
323
+ ```
324
+
325
+ ## NestJS Pattern
326
+
327
+ ```typescript
328
+ // users/users.controller.ts
329
+ import {
330
+ Controller,
331
+ Get,
332
+ Post,
333
+ Put,
334
+ Delete,
335
+ Body,
336
+ Param,
337
+ Query,
338
+ } from "@nestjs/common";
339
+ import { ApiTags, ApiOperation, ApiResponse } from "@nestjs/swagger";
340
+ import { UsersService } from "./users.service";
341
+ import { CreateUserDto, UpdateUserDto, GetUsersQueryDto } from "./dto";
342
+
343
+ @ApiTags("users")
344
+ @Controller("users")
345
+ export class UsersController {
346
+ constructor(private readonly usersService: UsersService) {}
347
+
348
+ @Post()
349
+ @ApiOperation({ summary: "Create user" })
350
+ @ApiResponse({ status: 201, description: "User created" })
351
+ @ApiResponse({ status: 400, description: "Validation error" })
352
+ async create(@Body() dto: CreateUserDto) {
353
+ return this.usersService.create(dto);
354
+ }
355
+
356
+ @Get()
357
+ @ApiOperation({ summary: "List users" })
358
+ async findAll(@Query() query: GetUsersQueryDto) {
359
+ return this.usersService.findAll(query);
360
+ }
361
+
362
+ @Get(":id")
363
+ @ApiOperation({ summary: "Get user by ID" })
364
+ async findOne(@Param("id") id: string) {
365
+ return this.usersService.findOne(id);
366
+ }
367
+
368
+ @Put(":id")
369
+ @ApiOperation({ summary: "Update user" })
370
+ async update(@Param("id") id: string, @Body() dto: UpdateUserDto) {
371
+ return this.usersService.update(id, dto);
372
+ }
373
+
374
+ @Delete(":id")
375
+ @ApiOperation({ summary: "Delete user" })
376
+ async remove(@Param("id") id: string) {
377
+ return this.usersService.remove(id);
378
+ }
379
+ }
380
+ ```
381
+
382
+ ## FastAPI Pattern (Python)
383
+
384
+ ```python
385
+ # routers/users.py
386
+ from fastapi import APIRouter, Depends, HTTPException, Query
387
+ from typing import List, Optional
388
+ from pydantic import BaseModel, EmailStr, Field
389
+
390
+ router = APIRouter(prefix="/users", tags=["users"])
391
+
392
+ class CreateUserDto(BaseModel):
393
+ email: EmailStr
394
+ name: str = Field(..., min_length=2)
395
+ password: str = Field(..., min_length=8)
396
+
397
+ class UserResponse(BaseModel):
398
+ id: str
399
+ email: str
400
+ name: str
401
+ role: str
402
+ created_at: datetime
403
+
404
+ class PaginatedResponse(BaseModel):
405
+ data: List[UserResponse]
406
+ total: int
407
+ page: int
408
+ limit: int
409
+
410
+ @router.post("/", status_code=201, response_model=UserResponse)
411
+ async def create_user(dto: CreateUserDto, service: UserService = Depends()):
412
+ return await service.create(dto)
413
+
414
+ @router.get("/", response_model=PaginatedResponse)
415
+ async def list_users(
416
+ page: int = Query(1, ge=1),
417
+ limit: int = Query(10, ge=1, le=100),
418
+ search: Optional[str] = None,
419
+ service: UserService = Depends()
420
+ ):
421
+ return await service.find_all(page, limit, search)
422
+ ```
423
+
424
+ ## Response Format Standards
425
+
426
+ ```typescript
427
+ // Success Response
428
+ {
429
+ "success": true,
430
+ "data": { ... },
431
+ "meta": {
432
+ "page": 1,
433
+ "limit": 10,
434
+ "total": 50,
435
+ "totalPages": 5
436
+ }
437
+ }
438
+
439
+ // Error Response
440
+ {
441
+ "success": false,
442
+ "error": {
443
+ "code": "VALIDATION_ERROR",
444
+ "message": "Invalid request data",
445
+ "details": {
446
+ "email": ["Invalid email address"],
447
+ "password": ["Password must contain uppercase letter"]
448
+ }
449
+ }
450
+ }
451
+ ```
452
+
453
+ ## Status Codes
454
+
455
+ - 200: Success (GET, PUT)
456
+ - 201: Created (POST)
457
+ - 204: No Content (DELETE)
458
+ - 400: Validation Error
459
+ - 401: Unauthorized
460
+ - 403: Forbidden
461
+ - 404: Not Found
462
+ - 409: Conflict
463
+ - 500: Server Error
464
+
465
+ ## Best Practices
466
+
467
+ 1. **Type everything**: Request, response, DTOs, errors
468
+ 2. **Validate early**: Before hitting service layer
469
+ 3. **Consistent responses**: Same structure everywhere
470
+ 4. **HTTP semantics**: Use correct status codes
471
+ 5. **Error details**: Include validation errors
472
+ 6. **Pagination**: Always paginate lists
473
+ 7. **Filtering/sorting**: Support common queries
474
+ 8. **Documentation**: OpenAPI/Swagger specs
475
+
476
+ ## Output Checklist
477
+
478
+ - [ ] Route definitions with HTTP methods
479
+ - [ ] Request validation schemas
480
+ - [ ] TypeScript types for all DTOs
481
+ - [ ] Controller handlers with error handling
482
+ - [ ] Consistent response format
483
+ - [ ] Pagination for list endpoints
484
+ - [ ] HTTP status codes correctly used
485
+ - [ ] Error response format
486
+ - [ ] OpenAPI/Swagger documentation
487
+ - [ ] Usage examples with curl/requests