@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,282 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @nextsparkjs/ai-workflow - Setup Script
|
|
5
|
+
*
|
|
6
|
+
* Copies AI workflow templates to the consumer's project directory.
|
|
7
|
+
* Uses file-by-file copy to preserve user-created files.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node node_modules/@nextsparkjs/ai-workflow/scripts/setup.mjs [editor]
|
|
11
|
+
* nextspark setup:ai --editor claude
|
|
12
|
+
*
|
|
13
|
+
* Editor options:
|
|
14
|
+
* claude Setup Claude Code (.claude/)
|
|
15
|
+
* cursor Setup Cursor (coming soon)
|
|
16
|
+
* antigravity Setup Antigravity (coming soon)
|
|
17
|
+
* all Setup all available editors
|
|
18
|
+
* (no arg) Defaults to "claude"
|
|
19
|
+
*
|
|
20
|
+
* Copy strategy:
|
|
21
|
+
* agents/, commands/, skills/, templates/, workflows/, _docs/
|
|
22
|
+
* → Overwrite matching files, preserve user-created files
|
|
23
|
+
* config/*.schema.json
|
|
24
|
+
* → Always overwrite (schema updates)
|
|
25
|
+
* config/*.json (non-schema)
|
|
26
|
+
* → Copy only if not exists (user config — never overwrite)
|
|
27
|
+
* sessions/
|
|
28
|
+
* → Create directory if not exists, never copy content
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import fs from 'node:fs'
|
|
32
|
+
import path from 'node:path'
|
|
33
|
+
import { fileURLToPath } from 'node:url'
|
|
34
|
+
|
|
35
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
36
|
+
const __dirname = path.dirname(__filename)
|
|
37
|
+
|
|
38
|
+
// Package root = where this script lives (packages/ai-workflow/ or node_modules/@nextsparkjs/ai-workflow/)
|
|
39
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..')
|
|
40
|
+
|
|
41
|
+
// Consumer project root = where the user runs from
|
|
42
|
+
const PROJECT_ROOT = process.cwd()
|
|
43
|
+
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Editor definitions
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
const EDITORS = {
|
|
49
|
+
claude: {
|
|
50
|
+
enabled: true,
|
|
51
|
+
source: 'claude', // subdirectory in package
|
|
52
|
+
target: '.claude', // subdirectory in consumer project
|
|
53
|
+
},
|
|
54
|
+
cursor: {
|
|
55
|
+
enabled: false,
|
|
56
|
+
source: 'cursor',
|
|
57
|
+
target: '.cursor',
|
|
58
|
+
},
|
|
59
|
+
antigravity: {
|
|
60
|
+
enabled: false,
|
|
61
|
+
source: 'antigravity',
|
|
62
|
+
target: '.antigravity',
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Copy strategies per directory
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/** Directories where matching files are overwritten */
|
|
71
|
+
const OVERWRITE_DIRS = new Set([
|
|
72
|
+
'agents',
|
|
73
|
+
'commands',
|
|
74
|
+
'skills',
|
|
75
|
+
'templates',
|
|
76
|
+
'workflows',
|
|
77
|
+
'_docs',
|
|
78
|
+
])
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Helpers
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
const colors = {
|
|
85
|
+
reset: '\x1b[0m',
|
|
86
|
+
cyan: '\x1b[36m',
|
|
87
|
+
green: '\x1b[32m',
|
|
88
|
+
yellow: '\x1b[33m',
|
|
89
|
+
blue: '\x1b[34m',
|
|
90
|
+
red: '\x1b[31m',
|
|
91
|
+
dim: '\x1b[2m',
|
|
92
|
+
bold: '\x1b[1m',
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function log(msg, color = 'reset') {
|
|
96
|
+
console.log(`${colors[color]}${msg}${colors.reset}`)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Recursively get all files in a directory (relative paths).
|
|
101
|
+
*/
|
|
102
|
+
function getAllFiles(dir, baseDir = dir) {
|
|
103
|
+
const results = []
|
|
104
|
+
if (!fs.existsSync(dir)) return results
|
|
105
|
+
|
|
106
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
107
|
+
const fullPath = path.join(dir, entry.name)
|
|
108
|
+
if (entry.isDirectory()) {
|
|
109
|
+
results.push(...getAllFiles(fullPath, baseDir))
|
|
110
|
+
} else if (entry.name !== '.gitkeep') {
|
|
111
|
+
results.push(path.relative(baseDir, fullPath))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return results
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Copy a single file, creating parent directories as needed.
|
|
119
|
+
*/
|
|
120
|
+
function copyFile(src, dest) {
|
|
121
|
+
const destDir = path.dirname(dest)
|
|
122
|
+
if (!fs.existsSync(destDir)) {
|
|
123
|
+
fs.mkdirSync(destDir, { recursive: true })
|
|
124
|
+
}
|
|
125
|
+
fs.copyFileSync(src, dest)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Setup logic for a single editor
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
function setupEditor(name, cfg) {
|
|
133
|
+
const sourceRoot = path.join(PACKAGE_ROOT, cfg.source)
|
|
134
|
+
const targetRoot = path.join(PROJECT_ROOT, cfg.target)
|
|
135
|
+
|
|
136
|
+
if (!fs.existsSync(sourceRoot)) {
|
|
137
|
+
log(` Source not found: ${sourceRoot}`, 'red')
|
|
138
|
+
return { overwritten: 0, created: 0, preserved: 0 }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Ensure target root exists
|
|
142
|
+
if (!fs.existsSync(targetRoot)) {
|
|
143
|
+
fs.mkdirSync(targetRoot, { recursive: true })
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let overwritten = 0
|
|
147
|
+
let created = 0
|
|
148
|
+
let preserved = 0
|
|
149
|
+
|
|
150
|
+
// 1. Process overwrite directories (agents, commands, skills, etc.)
|
|
151
|
+
for (const dirName of OVERWRITE_DIRS) {
|
|
152
|
+
const srcDir = path.join(sourceRoot, dirName)
|
|
153
|
+
if (!fs.existsSync(srcDir)) continue
|
|
154
|
+
|
|
155
|
+
const files = getAllFiles(srcDir)
|
|
156
|
+
for (const relPath of files) {
|
|
157
|
+
const srcFile = path.join(srcDir, relPath)
|
|
158
|
+
const destFile = path.join(targetRoot, dirName, relPath)
|
|
159
|
+
const existed = fs.existsSync(destFile)
|
|
160
|
+
|
|
161
|
+
copyFile(srcFile, destFile)
|
|
162
|
+
|
|
163
|
+
if (existed) {
|
|
164
|
+
overwritten++
|
|
165
|
+
} else {
|
|
166
|
+
created++
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (files.length > 0) {
|
|
171
|
+
log(` ${dirName}/: ${files.length} files`, 'green')
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 2. Process config/ directory with mixed strategy
|
|
176
|
+
const srcConfig = path.join(sourceRoot, 'config')
|
|
177
|
+
const destConfig = path.join(targetRoot, 'config')
|
|
178
|
+
|
|
179
|
+
if (fs.existsSync(srcConfig)) {
|
|
180
|
+
if (!fs.existsSync(destConfig)) {
|
|
181
|
+
fs.mkdirSync(destConfig, { recursive: true })
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let schemasCopied = 0
|
|
185
|
+
let configsCreated = 0
|
|
186
|
+
let configsPreserved = 0
|
|
187
|
+
|
|
188
|
+
for (const file of fs.readdirSync(srcConfig)) {
|
|
189
|
+
const srcFile = path.join(srcConfig, file)
|
|
190
|
+
const destFile = path.join(destConfig, file)
|
|
191
|
+
|
|
192
|
+
// Skip non-files and .gitkeep
|
|
193
|
+
if (!fs.statSync(srcFile).isFile() || file === '.gitkeep') continue
|
|
194
|
+
|
|
195
|
+
const isSchema = file.endsWith('.schema.json')
|
|
196
|
+
|
|
197
|
+
if (isSchema) {
|
|
198
|
+
// Schema files: always overwrite
|
|
199
|
+
copyFile(srcFile, destFile)
|
|
200
|
+
schemasCopied++
|
|
201
|
+
overwritten++
|
|
202
|
+
} else {
|
|
203
|
+
// Config files: copy only if not exists
|
|
204
|
+
if (fs.existsSync(destFile)) {
|
|
205
|
+
configsPreserved++
|
|
206
|
+
preserved++
|
|
207
|
+
} else {
|
|
208
|
+
copyFile(srcFile, destFile)
|
|
209
|
+
configsCreated++
|
|
210
|
+
created++
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (schemasCopied > 0) {
|
|
216
|
+
log(` config/*.schema.json: ${schemasCopied} schemas updated`, 'green')
|
|
217
|
+
}
|
|
218
|
+
if (configsCreated > 0) {
|
|
219
|
+
log(` config/*.json: ${configsCreated} new configs created`, 'green')
|
|
220
|
+
}
|
|
221
|
+
if (configsPreserved > 0) {
|
|
222
|
+
log(` config/*.json: ${configsPreserved} user configs preserved`, 'blue')
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 3. Ensure sessions/ directory exists (never copy content)
|
|
227
|
+
const sessionsDir = path.join(targetRoot, 'sessions')
|
|
228
|
+
if (!fs.existsSync(sessionsDir)) {
|
|
229
|
+
fs.mkdirSync(sessionsDir, { recursive: true })
|
|
230
|
+
log(` sessions/: created (empty)`, 'green')
|
|
231
|
+
} else {
|
|
232
|
+
log(` sessions/: exists (preserved)`, 'blue')
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return { overwritten, created, preserved }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ---------------------------------------------------------------------------
|
|
239
|
+
// Entry point
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
const editorArg = process.argv[2] || 'claude'
|
|
243
|
+
|
|
244
|
+
log(`\n${colors.bold}@nextsparkjs/ai-workflow — Setup${colors.reset}\n`, 'cyan')
|
|
245
|
+
log(`Package: ${PACKAGE_ROOT}`, 'dim')
|
|
246
|
+
log(`Project: ${PROJECT_ROOT}\n`, 'dim')
|
|
247
|
+
|
|
248
|
+
if (editorArg === 'all') {
|
|
249
|
+
for (const [name, cfg] of Object.entries(EDITORS)) {
|
|
250
|
+
if (cfg.enabled) {
|
|
251
|
+
log(`Setting up ${name}:`, 'cyan')
|
|
252
|
+
const stats = setupEditor(name, cfg)
|
|
253
|
+
log(` Total: ${stats.overwritten} updated, ${stats.created} created, ${stats.preserved} preserved\n`, 'dim')
|
|
254
|
+
} else {
|
|
255
|
+
log(`${name}: coming soon\n`, 'yellow')
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
const cfg = EDITORS[editorArg]
|
|
260
|
+
|
|
261
|
+
if (!cfg) {
|
|
262
|
+
log(`Unknown editor: ${editorArg}`, 'red')
|
|
263
|
+
log(`Available: ${Object.keys(EDITORS).join(', ')}, all`, 'dim')
|
|
264
|
+
process.exit(1)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (!cfg.enabled) {
|
|
268
|
+
log(`${editorArg}: coming soon`, 'yellow')
|
|
269
|
+
log(`Currently supported: claude`, 'dim')
|
|
270
|
+
process.exit(0)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
log(`Setting up ${editorArg}:`, 'cyan')
|
|
274
|
+
const stats = setupEditor(editorArg, cfg)
|
|
275
|
+
|
|
276
|
+
log('')
|
|
277
|
+
log(`Setup complete!`, 'green')
|
|
278
|
+
log(` ${stats.overwritten} files updated`, 'dim')
|
|
279
|
+
log(` ${stats.created} files created`, 'dim')
|
|
280
|
+
log(` ${stats.preserved} files preserved`, 'dim')
|
|
281
|
+
log('')
|
|
282
|
+
}
|
package/scripts/sync.mjs
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @nextsparkjs/ai-workflow - Sync Script
|
|
5
|
+
*
|
|
6
|
+
* Syncs the monorepo's working .claude/ directory into the publishable
|
|
7
|
+
* packages/ai-workflow/claude/ directory. Run manually before npm publish.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node packages/ai-workflow/scripts/sync.mjs
|
|
11
|
+
* # or from package dir:
|
|
12
|
+
* pnpm sync
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import fs from 'node:fs'
|
|
16
|
+
import path from 'node:path'
|
|
17
|
+
import { fileURLToPath } from 'node:url'
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
20
|
+
const __dirname = path.dirname(__filename)
|
|
21
|
+
|
|
22
|
+
// Package root = packages/ai-workflow/
|
|
23
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..')
|
|
24
|
+
// Monorepo root = repo/
|
|
25
|
+
const MONOREPO_ROOT = path.resolve(PACKAGE_ROOT, '../..')
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Editor definitions (future-proof)
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
const EDITORS = {
|
|
32
|
+
claude: {
|
|
33
|
+
sourceDir: '.claude',
|
|
34
|
+
targetDir: 'claude',
|
|
35
|
+
enabled: true,
|
|
36
|
+
},
|
|
37
|
+
cursor: {
|
|
38
|
+
sourceDir: '.cursor',
|
|
39
|
+
targetDir: 'cursor',
|
|
40
|
+
enabled: false,
|
|
41
|
+
},
|
|
42
|
+
antigravity: {
|
|
43
|
+
sourceDir: '.antigravity',
|
|
44
|
+
targetDir: 'antigravity',
|
|
45
|
+
enabled: false,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Sync mapping: directories and files to copy from .claude/ to claude/
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
/** Directories to sync (cleaned before copy) */
|
|
54
|
+
const SYNC_DIRS = [
|
|
55
|
+
'agents',
|
|
56
|
+
'commands',
|
|
57
|
+
'skills',
|
|
58
|
+
'templates',
|
|
59
|
+
'workflows',
|
|
60
|
+
'_docs',
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
/** Subdirectories to exclude from sync (monorepo-only content) */
|
|
64
|
+
const EXCLUDE_DIRS = new Set(['_monorepo'])
|
|
65
|
+
|
|
66
|
+
/** File globs within config/ to sync (only schemas) */
|
|
67
|
+
const CONFIG_SYNC_PATTERN = /\.schema\.json$/
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Helpers
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
const colors = {
|
|
74
|
+
reset: '\x1b[0m',
|
|
75
|
+
cyan: '\x1b[36m',
|
|
76
|
+
green: '\x1b[32m',
|
|
77
|
+
yellow: '\x1b[33m',
|
|
78
|
+
red: '\x1b[31m',
|
|
79
|
+
dim: '\x1b[2m',
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function log(msg, color = 'reset') {
|
|
83
|
+
console.log(`${colors[color]}${msg}${colors.reset}`)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getAllFiles(dir, baseDir = dir) {
|
|
87
|
+
const results = []
|
|
88
|
+
if (!fs.existsSync(dir)) return results
|
|
89
|
+
|
|
90
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
91
|
+
if (EXCLUDE_DIRS.has(entry.name)) continue
|
|
92
|
+
const fullPath = path.join(dir, entry.name)
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
results.push(...getAllFiles(fullPath, baseDir))
|
|
95
|
+
} else {
|
|
96
|
+
results.push(path.relative(baseDir, fullPath))
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return results
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function removeDir(dir) {
|
|
103
|
+
if (fs.existsSync(dir)) {
|
|
104
|
+
fs.rmSync(dir, { recursive: true, force: true })
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function copyFile(src, dest) {
|
|
109
|
+
const destDir = path.dirname(dest)
|
|
110
|
+
if (!fs.existsSync(destDir)) {
|
|
111
|
+
fs.mkdirSync(destDir, { recursive: true })
|
|
112
|
+
}
|
|
113
|
+
fs.copyFileSync(src, dest)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Main sync logic
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
function syncEditor(name, cfg) {
|
|
121
|
+
const sourceRoot = path.join(MONOREPO_ROOT, cfg.sourceDir)
|
|
122
|
+
const targetRoot = path.join(PACKAGE_ROOT, cfg.targetDir)
|
|
123
|
+
|
|
124
|
+
if (!fs.existsSync(sourceRoot)) {
|
|
125
|
+
log(` Source not found: ${sourceRoot}`, 'red')
|
|
126
|
+
return { copied: 0, removed: 0, skipped: 0 }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let copied = 0
|
|
130
|
+
let removed = 0
|
|
131
|
+
let skipped = 0
|
|
132
|
+
|
|
133
|
+
// 1. Sync directories: clean target then copy
|
|
134
|
+
for (const dirName of SYNC_DIRS) {
|
|
135
|
+
const srcDir = path.join(sourceRoot, dirName)
|
|
136
|
+
const destDir = path.join(targetRoot, dirName)
|
|
137
|
+
|
|
138
|
+
if (!fs.existsSync(srcDir)) {
|
|
139
|
+
skipped++
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Clean target directory (remove stale files)
|
|
144
|
+
if (fs.existsSync(destDir)) {
|
|
145
|
+
const oldFiles = getAllFiles(destDir)
|
|
146
|
+
removeDir(destDir)
|
|
147
|
+
removed += oldFiles.length
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Copy all files
|
|
151
|
+
const files = getAllFiles(srcDir)
|
|
152
|
+
for (const relPath of files) {
|
|
153
|
+
copyFile(
|
|
154
|
+
path.join(srcDir, relPath),
|
|
155
|
+
path.join(destDir, relPath)
|
|
156
|
+
)
|
|
157
|
+
copied++
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
log(` ${dirName}/: ${files.length} files`, 'green')
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 2. Sync config/ schemas only
|
|
164
|
+
const srcConfig = path.join(sourceRoot, 'config')
|
|
165
|
+
const destConfig = path.join(targetRoot, 'config')
|
|
166
|
+
|
|
167
|
+
if (fs.existsSync(srcConfig)) {
|
|
168
|
+
let schemaCount = 0
|
|
169
|
+
for (const file of fs.readdirSync(srcConfig)) {
|
|
170
|
+
if (CONFIG_SYNC_PATTERN.test(file)) {
|
|
171
|
+
copyFile(
|
|
172
|
+
path.join(srcConfig, file),
|
|
173
|
+
path.join(destConfig, file)
|
|
174
|
+
)
|
|
175
|
+
schemaCount++
|
|
176
|
+
copied++
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
log(` config/*.schema.json: ${schemaCount} files`, 'green')
|
|
180
|
+
log(` config/*.json (templates): preserved`, 'dim')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return { copied, removed, skipped }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
// Entry point
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
log('\n@nextsparkjs/ai-workflow — Sync\n', 'cyan')
|
|
191
|
+
log(`Source: ${MONOREPO_ROOT}/.claude/`, 'dim')
|
|
192
|
+
log(`Target: ${PACKAGE_ROOT}/claude/\n`, 'dim')
|
|
193
|
+
|
|
194
|
+
let totalCopied = 0
|
|
195
|
+
let totalRemoved = 0
|
|
196
|
+
|
|
197
|
+
for (const [name, cfg] of Object.entries(EDITORS)) {
|
|
198
|
+
if (!cfg.enabled) {
|
|
199
|
+
log(`${name}: coming soon (skipped)`, 'dim')
|
|
200
|
+
continue
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
log(`Syncing ${name}:`, 'cyan')
|
|
204
|
+
const stats = syncEditor(name, cfg)
|
|
205
|
+
totalCopied += stats.copied
|
|
206
|
+
totalRemoved += stats.removed
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
log(`\nDone: ${totalCopied} files copied, ${totalRemoved} stale files removed.\n`, 'green')
|