@nextsparkjs/ai-workflow 0.1.0-beta.86
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.
- package/LICENSE +21 -0
- package/README.md +86 -0
- package/claude/_docs/workflows-optimizations.md +359 -0
- package/claude/agents/api-tester.md +636 -0
- package/claude/agents/architecture-supervisor.md +1381 -0
- package/claude/agents/backend-developer.md +1021 -0
- package/claude/agents/backend-validator.md +417 -0
- package/claude/agents/bdd-docs-writer.md +737 -0
- package/claude/agents/block-developer.md +677 -0
- package/claude/agents/code-reviewer.md +1460 -0
- package/claude/agents/db-developer.md +721 -0
- package/claude/agents/db-validator.md +407 -0
- package/claude/agents/demo-video-generator.md +493 -0
- package/claude/agents/documentation-writer.md +1291 -0
- package/claude/agents/frontend-developer.md +1259 -0
- package/claude/agents/frontend-validator.md +777 -0
- package/claude/agents/functional-validator.md +630 -0
- package/claude/agents/mock-analyst.md +387 -0
- package/claude/agents/product-manager.md +971 -0
- package/claude/agents/qa-automation.md +1762 -0
- package/claude/agents/release-manager.md +634 -0
- package/claude/agents/selectors-translator.md +262 -0
- package/claude/agents/unit-test-writer.md +785 -0
- package/claude/agents/visual-comparator.md +329 -0
- package/claude/agents/workflow-maintainer.md +373 -0
- package/claude/commands/do/README.md +88 -0
- package/claude/commands/do/create-api.md +64 -0
- package/claude/commands/do/create-entity.md +66 -0
- package/claude/commands/do/create-migration.md +64 -0
- package/claude/commands/do/create-plugin.md +56 -0
- package/claude/commands/do/create-theme.md +70 -0
- package/claude/commands/do/mock-data.md +67 -0
- package/claude/commands/do/reset-db.md +71 -0
- package/claude/commands/do/setup-scheduled-action.md +75 -0
- package/claude/commands/do/sync-code-review.md +117 -0
- package/claude/commands/do/update-selectors.md +112 -0
- package/claude/commands/do/use-skills.md +90 -0
- package/claude/commands/do/validate-blocks.md +69 -0
- package/claude/commands/how-to/README.md +261 -0
- package/claude/commands/how-to/add-metadata.md +692 -0
- package/claude/commands/how-to/add-taxonomies.md +806 -0
- package/claude/commands/how-to/add-translations.md +571 -0
- package/claude/commands/how-to/create-api.md +577 -0
- package/claude/commands/how-to/create-block.md +575 -0
- package/claude/commands/how-to/create-child-entities.md +771 -0
- package/claude/commands/how-to/create-entity.md +597 -0
- package/claude/commands/how-to/create-migrations.md +605 -0
- package/claude/commands/how-to/create-plugin.md +654 -0
- package/claude/commands/how-to/customize-app.md +481 -0
- package/claude/commands/how-to/customize-dashboard.md +553 -0
- package/claude/commands/how-to/customize-theme.md +438 -0
- package/claude/commands/how-to/define-features-flows.md +632 -0
- package/claude/commands/how-to/deploy.md +507 -0
- package/claude/commands/how-to/handle-file-uploads.md +681 -0
- package/claude/commands/how-to/implement-search.md +1001 -0
- package/claude/commands/how-to/install-plugins.md +352 -0
- package/claude/commands/how-to/manage-test-coverage.md +984 -0
- package/claude/commands/how-to/run-tests.md +400 -0
- package/claude/commands/how-to/set-app-languages.md +601 -0
- package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
- package/claude/commands/how-to/set-scheduled-actions.md +527 -0
- package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
- package/claude/commands/how-to/setup-authentication.md +388 -0
- package/claude/commands/how-to/setup-claude-code.md +512 -0
- package/claude/commands/how-to/setup-database.md +274 -0
- package/claude/commands/how-to/setup-email-providers.md +598 -0
- package/claude/commands/how-to/setup-mobile-dev.md +627 -0
- package/claude/commands/how-to/start.md +455 -0
- package/claude/commands/how-to/use-devtools.md +639 -0
- package/claude/commands/how-to/use-superadmin.md +622 -0
- package/claude/commands/session/README.md +193 -0
- package/claude/commands/session/block-create.md +190 -0
- package/claude/commands/session/block-list.md +203 -0
- package/claude/commands/session/block-update.md +192 -0
- package/claude/commands/session/block-validate.md +218 -0
- package/claude/commands/session/close.md +146 -0
- package/claude/commands/session/commit.md +174 -0
- package/claude/commands/session/db-entity.md +206 -0
- package/claude/commands/session/db-fix.md +212 -0
- package/claude/commands/session/db-sample.md +206 -0
- package/claude/commands/session/demo.md +178 -0
- package/claude/commands/session/doc-bdd.md +207 -0
- package/claude/commands/session/doc-feature.md +218 -0
- package/claude/commands/session/doc-read.md +225 -0
- package/claude/commands/session/execute.md +204 -0
- package/claude/commands/session/explain.md +202 -0
- package/claude/commands/session/fix-bug.md +210 -0
- package/claude/commands/session/fix-build.md +182 -0
- package/claude/commands/session/fix-test.md +189 -0
- package/claude/commands/session/pending.md +232 -0
- package/claude/commands/session/refine.md +188 -0
- package/claude/commands/session/resume.md +192 -0
- package/claude/commands/session/review.md +192 -0
- package/claude/commands/session/scope-change.md +181 -0
- package/claude/commands/session/start-blocks.md +347 -0
- package/claude/commands/session/start.md +476 -0
- package/claude/commands/session/status.md +169 -0
- package/claude/commands/session/test-fix.md +221 -0
- package/claude/commands/session/test-run.md +203 -0
- package/claude/commands/session/test-write.md +242 -0
- package/claude/commands/session/validate.md +162 -0
- package/claude/config/context.json +54 -0
- package/claude/config/github.json +69 -0
- package/claude/config/github.schema.json +106 -0
- package/claude/config/team.json +46 -0
- package/claude/config/team.schema.json +106 -0
- package/claude/config/workspace.json +49 -0
- package/claude/config/workspace.schema.json +64 -0
- package/claude/scripts/.gitkeep +0 -0
- package/claude/sessions/.gitkeep +0 -0
- package/claude/skills/README.md +228 -0
- package/claude/skills/accessibility/SKILL.md +573 -0
- package/claude/skills/api-bypass-layers/SKILL.md +550 -0
- package/claude/skills/asana-integration/SKILL.md +499 -0
- package/claude/skills/better-auth/SKILL.md +666 -0
- package/claude/skills/billing-subscriptions/SKILL.md +660 -0
- package/claude/skills/block-decision-matrix/SKILL.md +359 -0
- package/claude/skills/clickup-integration/SKILL.md +434 -0
- package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
- package/claude/skills/create-plugin/SKILL.md +425 -0
- package/claude/skills/create-theme/SKILL.md +331 -0
- package/claude/skills/cypress-api/SKILL.md +511 -0
- package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
- package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
- package/claude/skills/cypress-e2e/SKILL.md +526 -0
- package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
- package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
- package/claude/skills/cypress-selectors/SKILL.md +309 -0
- package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
- package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
- package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
- package/claude/skills/database-migrations/SKILL.md +335 -0
- package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
- package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
- package/claude/skills/design-system/SKILL.md +682 -0
- package/claude/skills/documentation/SKILL.md +540 -0
- package/claude/skills/entity-api/SKILL.md +482 -0
- package/claude/skills/entity-system/SKILL.md +635 -0
- package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
- package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
- package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
- package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
- package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
- package/claude/skills/github/SKILL.md +467 -0
- package/claude/skills/i18n-nextintl/SKILL.md +302 -0
- package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
- package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
- package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
- package/claude/skills/impact-analysis/SKILL.md +203 -0
- package/claude/skills/jest-unit/SKILL.md +306 -0
- package/claude/skills/jest-unit/references/component-testing.md +371 -0
- package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
- package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
- package/claude/skills/jira-integration/SKILL.md +539 -0
- package/claude/skills/mock-analysis/SKILL.md +276 -0
- package/claude/skills/monorepo-architecture/SKILL.md +162 -0
- package/claude/skills/nextjs-api-development/SKILL.md +364 -0
- package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
- package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
- package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
- package/claude/skills/notion-integration/SKILL.md +641 -0
- package/claude/skills/npm-development-workflow/SKILL.md +480 -0
- package/claude/skills/page-builder-blocks/SKILL.md +483 -0
- package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
- package/claude/skills/permissions-system/SKILL.md +619 -0
- package/claude/skills/plugins/SKILL.md +340 -0
- package/claude/skills/plugins/references/plugin-templates.md +414 -0
- package/claude/skills/plugins/references/plugin-testing.md +353 -0
- package/claude/skills/plugins/references/plugin-types.md +198 -0
- package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
- package/claude/skills/pom-patterns/SKILL.md +452 -0
- package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
- package/claude/skills/rate-limiting/SKILL.md +342 -0
- package/claude/skills/react-best-practices/AGENTS.md +2410 -0
- package/claude/skills/react-best-practices/README.md +123 -0
- package/claude/skills/react-best-practices/SKILL.md +125 -0
- package/claude/skills/react-best-practices/metadata.json +15 -0
- package/claude/skills/react-best-practices/rules/_sections.md +46 -0
- package/claude/skills/react-best-practices/rules/_template.md +28 -0
- package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/claude/skills/react-patterns/SKILL.md +677 -0
- package/claude/skills/registry-system/SKILL.md +331 -0
- package/claude/skills/scheduled-actions/SKILL.md +431 -0
- package/claude/skills/scope-enforcement/SKILL.md +542 -0
- package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
- package/claude/skills/server-actions/SKILL.md +493 -0
- package/claude/skills/service-layer/SKILL.md +587 -0
- package/claude/skills/session-management/SKILL.md +266 -0
- package/claude/skills/session-management/scripts/create-session.py +166 -0
- package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
- package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
- package/claude/skills/session-management/scripts/session-archive.sh +87 -0
- package/claude/skills/session-management/scripts/session-close.sh +133 -0
- package/claude/skills/session-management/scripts/session-init.sh +225 -0
- package/claude/skills/session-management/scripts/session-list.sh +163 -0
- package/claude/skills/session-management/scripts/split-plan.sh +116 -0
- package/claude/skills/shadcn-components/SKILL.md +586 -0
- package/claude/skills/shadcn-theming/SKILL.md +446 -0
- package/claude/skills/suspense-loading/SKILL.md +280 -0
- package/claude/skills/tailwind-theming/SKILL.md +479 -0
- package/claude/skills/tanstack-query/SKILL.md +608 -0
- package/claude/skills/test-coverage/SKILL.md +239 -0
- package/claude/skills/web-design-guidelines/SKILL.md +39 -0
- package/claude/skills/zod-validation/SKILL.md +537 -0
- package/claude/templates/blocks/progress.md +86 -0
- package/claude/templates/iteration/changes.md +61 -0
- package/claude/templates/iteration/progress.md +55 -0
- package/claude/templates/log.md +31 -0
- package/claude/templates/story/context.md +77 -0
- package/claude/templates/story/pendings.md +37 -0
- package/claude/templates/story/plan.md +299 -0
- package/claude/templates/story/requirements.md +109 -0
- package/claude/templates/story/scope.json +10 -0
- package/claude/templates/story/tests.md +91 -0
- package/claude/templates/task/progress.md +58 -0
- package/claude/templates/task/requirements.md +54 -0
- package/claude/workflows/README.md +154 -0
- package/claude/workflows/blocks.md +614 -0
- package/claude/workflows/story.md +1207 -0
- package/claude/workflows/task.md +927 -0
- package/claude/workflows/tweak.md +527 -0
- package/cursor/.gitkeep +0 -0
- package/package.json +34 -0
- package/scripts/setup.mjs +282 -0
- package/scripts/sync.mjs +209 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scheduled-actions
|
|
3
|
+
description: |
|
|
4
|
+
Scheduled Actions system for background task processing in this application.
|
|
5
|
+
Covers action scheduling, handler creation, webhook configuration, and cron processing.
|
|
6
|
+
Use this skill when creating, debugging, or configuring scheduled actions.
|
|
7
|
+
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
|
|
8
|
+
version: 1.0.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Scheduled Actions Skill
|
|
12
|
+
|
|
13
|
+
Patterns for background task processing and webhook systems.
|
|
14
|
+
|
|
15
|
+
## Architecture Overview
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
SCHEDULED ACTIONS SYSTEM:
|
|
19
|
+
|
|
20
|
+
Core Layer (core/lib/scheduled-actions/):
|
|
21
|
+
├── scheduler.ts # scheduleAction(), scheduleRecurringAction()
|
|
22
|
+
├── processor.ts # Cron processing logic
|
|
23
|
+
├── registry.ts # Handler registration
|
|
24
|
+
└── types.ts # TypeScript interfaces
|
|
25
|
+
|
|
26
|
+
Theme Layer (contents/themes/{theme}/lib/scheduled-actions/):
|
|
27
|
+
├── index.ts # Handler initialization + registerAllHandlers()
|
|
28
|
+
├── entity-hooks.ts # Entity event → action mapping
|
|
29
|
+
└── handlers/ # Handler implementations
|
|
30
|
+
├── webhook.ts # Webhook sender
|
|
31
|
+
├── email.ts # Email sender (if configured)
|
|
32
|
+
└── {custom}.ts # Custom handlers
|
|
33
|
+
|
|
34
|
+
Configuration (contents/themes/{theme}/config/app.config.ts):
|
|
35
|
+
└── scheduledActions: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
deduplication: { windowSeconds: 10 },
|
|
38
|
+
webhooks: { endpoints: {...}, patterns: {...} }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Flow:
|
|
42
|
+
Entity Event → Entity Hook → scheduleAction() → DB Table → Cron → Handler → Result
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> **📍 Context-Aware Paths:** Core layer (`core/lib/scheduled-actions/`) is read-only in consumer projects.
|
|
46
|
+
> Create handlers in `contents/themes/{theme}/lib/scheduled-actions/handlers/`.
|
|
47
|
+
> See `core-theme-responsibilities` skill for complete rules.
|
|
48
|
+
|
|
49
|
+
## When to Use This Skill
|
|
50
|
+
|
|
51
|
+
- Creating new action handlers
|
|
52
|
+
- Setting up webhooks for entity events
|
|
53
|
+
- Debugging pending/failed actions
|
|
54
|
+
- Configuring deduplication or batching
|
|
55
|
+
- Understanding the scheduled actions flow
|
|
56
|
+
|
|
57
|
+
## Key Files Reference
|
|
58
|
+
|
|
59
|
+
| File | Purpose |
|
|
60
|
+
|------|---------|
|
|
61
|
+
| `core/lib/scheduled-actions/scheduler.ts` | `scheduleAction()`, `scheduleRecurringAction()` |
|
|
62
|
+
| `core/lib/scheduled-actions/processor.ts` | Cron processing logic |
|
|
63
|
+
| `core/lib/scheduled-actions/registry.ts` | Handler registration |
|
|
64
|
+
| `contents/themes/{theme}/lib/scheduled-actions/index.ts` | Handler initialization |
|
|
65
|
+
| `contents/themes/{theme}/lib/scheduled-actions/handlers/` | Handler implementations |
|
|
66
|
+
| `contents/themes/{theme}/config/app.config.ts` | Configuration section |
|
|
67
|
+
|
|
68
|
+
## Creating Action Handlers
|
|
69
|
+
|
|
70
|
+
### Handler Template
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// contents/themes/{theme}/lib/scheduled-actions/handlers/{name}.ts
|
|
74
|
+
import { registerScheduledAction } from '@/core/lib/scheduled-actions'
|
|
75
|
+
|
|
76
|
+
interface MyPayload {
|
|
77
|
+
entityId: string
|
|
78
|
+
teamId: string
|
|
79
|
+
data: Record<string, unknown>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function registerMyHandler() {
|
|
83
|
+
registerScheduledAction('my-action:type', async (payload, action) => {
|
|
84
|
+
const data = payload as MyPayload
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Implementation logic
|
|
88
|
+
await processMyAction(data)
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
success: true,
|
|
92
|
+
message: 'Action completed successfully'
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Registering Handler
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// contents/themes/{theme}/lib/scheduled-actions/index.ts
|
|
108
|
+
import { registerMyHandler } from './handlers/my-handler'
|
|
109
|
+
|
|
110
|
+
let initialized = false
|
|
111
|
+
|
|
112
|
+
export function registerAllHandlers() {
|
|
113
|
+
if (initialized) return
|
|
114
|
+
initialized = true
|
|
115
|
+
|
|
116
|
+
// Register all handlers
|
|
117
|
+
registerWebhookHandler()
|
|
118
|
+
registerMyHandler() // Add new handler here
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Handler Types
|
|
123
|
+
|
|
124
|
+
| Type | Description | Use Case |
|
|
125
|
+
|------|-------------|----------|
|
|
126
|
+
| `webhook` | Send HTTP POST to external endpoint | Integrations, notifications |
|
|
127
|
+
| `email` | Send transactional emails | User notifications |
|
|
128
|
+
| `data-processor` | Process/transform data | ETL, aggregations |
|
|
129
|
+
| `cleanup` | Clean up old records | Maintenance tasks |
|
|
130
|
+
|
|
131
|
+
## Webhook Configuration
|
|
132
|
+
|
|
133
|
+
### Entity Hook Pattern
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
// contents/themes/{theme}/lib/scheduled-actions/entity-hooks.ts
|
|
137
|
+
import { scheduleAction } from '@/core/lib/scheduled-actions'
|
|
138
|
+
import { hookSystem } from '@/core/lib/hooks'
|
|
139
|
+
|
|
140
|
+
export function registerEntityHooks() {
|
|
141
|
+
// Hook for task creation
|
|
142
|
+
hookSystem.register('entity.tasks.created', async ({ entity, teamId }) => {
|
|
143
|
+
await scheduleAction({
|
|
144
|
+
type: 'webhook:send',
|
|
145
|
+
payload: {
|
|
146
|
+
endpointKey: 'tasks',
|
|
147
|
+
event: 'task.created',
|
|
148
|
+
data: entity
|
|
149
|
+
},
|
|
150
|
+
scheduledFor: new Date(),
|
|
151
|
+
teamId
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Hook for task updates
|
|
156
|
+
hookSystem.register('entity.tasks.updated', async ({ entity, teamId }) => {
|
|
157
|
+
await scheduleAction({
|
|
158
|
+
type: 'webhook:send',
|
|
159
|
+
payload: {
|
|
160
|
+
endpointKey: 'tasks',
|
|
161
|
+
event: 'task.updated',
|
|
162
|
+
data: entity
|
|
163
|
+
},
|
|
164
|
+
scheduledFor: new Date(),
|
|
165
|
+
teamId
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Webhook Configuration in app.config.ts
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// contents/themes/{theme}/config/app.config.ts
|
|
175
|
+
export const appConfig = {
|
|
176
|
+
// ... other config
|
|
177
|
+
|
|
178
|
+
scheduledActions: {
|
|
179
|
+
enabled: true,
|
|
180
|
+
|
|
181
|
+
deduplication: {
|
|
182
|
+
windowSeconds: 10 // 0 to disable
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
webhooks: {
|
|
186
|
+
endpoints: {
|
|
187
|
+
// Key -> Environment variable mapping
|
|
188
|
+
tasks: 'WEBHOOK_URL_TASKS',
|
|
189
|
+
subscriptions: 'WEBHOOK_URL_SUBSCRIPTIONS',
|
|
190
|
+
default: 'WEBHOOK_URL_DEFAULT'
|
|
191
|
+
},
|
|
192
|
+
patterns: {
|
|
193
|
+
// Event pattern -> Endpoint key
|
|
194
|
+
'task.*': 'tasks',
|
|
195
|
+
'subscription.*': 'subscriptions',
|
|
196
|
+
'*': 'default' // Fallback
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Environment Variables
|
|
204
|
+
|
|
205
|
+
```env
|
|
206
|
+
# Required for cron processing
|
|
207
|
+
CRON_SECRET=your-secure-secret-min-32-chars
|
|
208
|
+
|
|
209
|
+
# Webhook URLs (one per endpoint key)
|
|
210
|
+
WEBHOOK_URL_TASKS=https://your-webhook-url/tasks
|
|
211
|
+
WEBHOOK_URL_SUBSCRIPTIONS=https://your-webhook-url/subs
|
|
212
|
+
WEBHOOK_URL_DEFAULT=https://fallback-url
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Scheduling Actions
|
|
216
|
+
|
|
217
|
+
### Immediate Action
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { scheduleAction } from '@/core/lib/scheduled-actions'
|
|
221
|
+
|
|
222
|
+
await scheduleAction({
|
|
223
|
+
type: 'my-action:type',
|
|
224
|
+
payload: {
|
|
225
|
+
entityId: 'abc123',
|
|
226
|
+
data: { field: 'value' }
|
|
227
|
+
},
|
|
228
|
+
scheduledFor: new Date(), // Now
|
|
229
|
+
teamId: 'team_123'
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Delayed Action
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
await scheduleAction({
|
|
237
|
+
type: 'reminder:send',
|
|
238
|
+
payload: { userId: 'user_123', message: 'Follow up' },
|
|
239
|
+
scheduledFor: new Date(Date.now() + 24 * 60 * 60 * 1000), // Tomorrow
|
|
240
|
+
teamId: 'team_123'
|
|
241
|
+
})
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Recurring Action
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { scheduleRecurringAction } from '@/core/lib/scheduled-actions'
|
|
248
|
+
|
|
249
|
+
await scheduleRecurringAction({
|
|
250
|
+
type: 'report:generate',
|
|
251
|
+
payload: { reportType: 'daily-summary' },
|
|
252
|
+
cron: '0 9 * * *', // Every day at 9 AM
|
|
253
|
+
teamId: 'team_123'
|
|
254
|
+
})
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Debugging Actions
|
|
258
|
+
|
|
259
|
+
### Check Pending Actions
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
curl "http://localhost:5173/api/v1/devtools/scheduled-actions?status=pending" \
|
|
263
|
+
-H "Authorization: Bearer API_KEY"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Check Failed Actions
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
curl "http://localhost:5173/api/v1/devtools/scheduled-actions?status=failed" \
|
|
270
|
+
-H "Authorization: Bearer API_KEY"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Manually Trigger Processing
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
curl "http://localhost:5173/api/v1/cron/process" \
|
|
277
|
+
-H "x-cron-secret: CRON_SECRET"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Console Log Patterns
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
[ScheduledActions] Processing 5 pending actions
|
|
284
|
+
[ScheduledActions] Action abc123 completed successfully
|
|
285
|
+
[ScheduledActions] Action xyz789 failed: Connection timeout
|
|
286
|
+
[ScheduledActions] Handler not found for type: unknown:type
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Deduplication
|
|
290
|
+
|
|
291
|
+
### Purpose
|
|
292
|
+
|
|
293
|
+
Prevents duplicate actions when the same event fires multiple times in quick succession.
|
|
294
|
+
|
|
295
|
+
### Configuration
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
scheduledActions: {
|
|
299
|
+
deduplication: {
|
|
300
|
+
windowSeconds: 10 // Actions with same type+payload within 10s are deduplicated
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Behavior
|
|
306
|
+
|
|
307
|
+
1. When action is scheduled, system creates hash of `type + payload`
|
|
308
|
+
2. If action with same hash exists within window, new action is skipped
|
|
309
|
+
3. Window is reset when action is processed
|
|
310
|
+
|
|
311
|
+
### Disabling
|
|
312
|
+
|
|
313
|
+
Set `windowSeconds: 0` to disable deduplication entirely.
|
|
314
|
+
|
|
315
|
+
## API Endpoints
|
|
316
|
+
|
|
317
|
+
| Endpoint | Method | Auth | Purpose |
|
|
318
|
+
|----------|--------|------|---------|
|
|
319
|
+
| `/api/v1/cron/process` | POST | x-cron-secret | Trigger action processing |
|
|
320
|
+
| `/api/v1/devtools/scheduled-actions` | GET | API Key | List actions (debug) |
|
|
321
|
+
| `/api/v1/devtools/scheduled-actions/:id` | DELETE | API Key | Delete action (debug) |
|
|
322
|
+
|
|
323
|
+
## Troubleshooting
|
|
324
|
+
|
|
325
|
+
| Issue | Cause | Solution |
|
|
326
|
+
|-------|-------|----------|
|
|
327
|
+
| Handler not found | Not registered | Add to `index.ts` `registerAllHandlers()` |
|
|
328
|
+
| Webhook not sent | Pattern mismatch | Check patterns in `app.config.ts` |
|
|
329
|
+
| Duplicate actions | Dedup disabled | Set `windowSeconds > 0` |
|
|
330
|
+
| Actions stuck pending | Cron not running | Verify cron service and `CRON_SECRET` |
|
|
331
|
+
| 401 on cron endpoint | Wrong header | Use `x-cron-secret` (not `Authorization`) |
|
|
332
|
+
| Env variable undefined | Not set | Add to `.env` and restart server |
|
|
333
|
+
|
|
334
|
+
## Anti-Patterns
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// NEVER: Process actions synchronously in API routes
|
|
338
|
+
// This blocks the response
|
|
339
|
+
app.post('/api/entity', async (req, res) => {
|
|
340
|
+
const entity = await createEntity(req.body)
|
|
341
|
+
await sendWebhook(entity) // WRONG - blocks response
|
|
342
|
+
res.json(entity)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
// CORRECT: Schedule action for async processing
|
|
346
|
+
app.post('/api/entity', async (req, res) => {
|
|
347
|
+
const entity = await createEntity(req.body)
|
|
348
|
+
await scheduleAction({
|
|
349
|
+
type: 'webhook:send',
|
|
350
|
+
payload: { entity },
|
|
351
|
+
scheduledFor: new Date(),
|
|
352
|
+
teamId: req.teamId
|
|
353
|
+
})
|
|
354
|
+
res.json(entity)
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
// NEVER: Store sensitive data in payload
|
|
358
|
+
await scheduleAction({
|
|
359
|
+
type: 'email:send',
|
|
360
|
+
payload: {
|
|
361
|
+
password: 'secret123' // WRONG - stored in DB
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
// CORRECT: Store references only
|
|
366
|
+
await scheduleAction({
|
|
367
|
+
type: 'email:send',
|
|
368
|
+
payload: {
|
|
369
|
+
userId: 'user_123', // Lookup at processing time
|
|
370
|
+
templateKey: 'password-reset'
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
// NEVER: Forget to handle errors in handlers
|
|
375
|
+
registerScheduledAction('my:action', async (payload) => {
|
|
376
|
+
await riskyOperation(payload) // WRONG - unhandled rejection
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
// CORRECT: Always return success/failure
|
|
380
|
+
registerScheduledAction('my:action', async (payload) => {
|
|
381
|
+
try {
|
|
382
|
+
await riskyOperation(payload)
|
|
383
|
+
return { success: true, message: 'Done' }
|
|
384
|
+
} catch (error) {
|
|
385
|
+
return { success: false, message: error.message }
|
|
386
|
+
}
|
|
387
|
+
})
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Checklist
|
|
391
|
+
|
|
392
|
+
### Creating New Handler
|
|
393
|
+
|
|
394
|
+
- [ ] Handler file created in `handlers/` directory
|
|
395
|
+
- [ ] Handler registered in `index.ts` `registerAllHandlers()`
|
|
396
|
+
- [ ] Handler returns `{ success, message }` object
|
|
397
|
+
- [ ] Error handling with try/catch
|
|
398
|
+
- [ ] Registry rebuilt: `node core/scripts/build/registry.mjs`
|
|
399
|
+
|
|
400
|
+
### Adding Webhook
|
|
401
|
+
|
|
402
|
+
- [ ] Entity hook registered in `entity-hooks.ts`
|
|
403
|
+
- [ ] Endpoint key added to `webhooks.endpoints` config
|
|
404
|
+
- [ ] Pattern added to `webhooks.patterns` config
|
|
405
|
+
- [ ] Environment variable added to `.env`
|
|
406
|
+
- [ ] Environment variable documented in `.env.example`
|
|
407
|
+
|
|
408
|
+
### Debugging
|
|
409
|
+
|
|
410
|
+
- [ ] Check if `scheduledActions.enabled: true` in config
|
|
411
|
+
- [ ] Verify `CRON_SECRET` is set
|
|
412
|
+
- [ ] Check handler is registered (console log on startup)
|
|
413
|
+
- [ ] Query devtools endpoint for action status
|
|
414
|
+
- [ ] Check console for `[ScheduledActions]` logs
|
|
415
|
+
|
|
416
|
+
## Related Skills
|
|
417
|
+
|
|
418
|
+
- `entity-api` - API endpoints that trigger entity hooks
|
|
419
|
+
- `service-layer` - Service patterns for action processing
|
|
420
|
+
- `nextjs-api-development` - Cron endpoint patterns
|
|
421
|
+
- `database-migrations` - scheduled_actions table structure
|
|
422
|
+
|
|
423
|
+
## Documentation
|
|
424
|
+
|
|
425
|
+
Full documentation: `core/docs/20-scheduled-actions/`
|
|
426
|
+
- `01-overview.md` - System overview
|
|
427
|
+
- `02-scheduling.md` - Scheduling patterns
|
|
428
|
+
- `03-handlers.md` - Handler development
|
|
429
|
+
- `04-webhooks.md` - Webhook configuration
|
|
430
|
+
- `05-cron.md` - Cron processing
|
|
431
|
+
- `06-deduplication.md` - Deduplication system
|