@nextsparkjs/ai-workflow 0.1.0-beta.88 → 0.1.0-beta.89
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/package.json +3 -2
- package/scripts/postinstall.mjs +170 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextsparkjs/ai-workflow",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.89",
|
|
4
4
|
"description": "AI workflow templates for NextSpark - Claude Code agents, commands, skills, and multi-editor support",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "NextSpark <hello@nextspark.dev>",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
31
|
"setup": "node scripts/setup.mjs",
|
|
32
|
-
"sync": "node scripts/sync.mjs"
|
|
32
|
+
"sync": "node scripts/sync.mjs",
|
|
33
|
+
"postinstall": "node scripts/postinstall.mjs"
|
|
33
34
|
}
|
|
34
35
|
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @nextsparkjs/ai-workflow postinstall hook
|
|
4
|
+
*
|
|
5
|
+
* Automatically syncs AI workflow files (.claude/, .cursor/, etc.) when the package is updated.
|
|
6
|
+
* Only runs in NextSpark projects that already have AI workflow set up.
|
|
7
|
+
*
|
|
8
|
+
* Debug mode: Set NEXTSPARK_DEBUG=1 to see detailed logs
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import { existsSync, readFileSync } from 'fs';
|
|
13
|
+
import { join, dirname, resolve, isAbsolute } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
|
|
16
|
+
const DEBUG = process.env.NEXTSPARK_DEBUG === '1';
|
|
17
|
+
|
|
18
|
+
function debug(message) {
|
|
19
|
+
if (DEBUG) {
|
|
20
|
+
console.log(` [DEBUG] ${message}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Find the project root by walking up from the current directory
|
|
26
|
+
* until we find a package.json that isn't inside node_modules
|
|
27
|
+
*/
|
|
28
|
+
function findProjectRoot() {
|
|
29
|
+
// When running postinstall, we're in node_modules/@nextsparkjs/ai-workflow
|
|
30
|
+
// We need to find the project root (where the user's package.json is)
|
|
31
|
+
let current = process.cwd();
|
|
32
|
+
|
|
33
|
+
// If we're inside node_modules, walk up to find the project root
|
|
34
|
+
if (current.includes('node_modules')) {
|
|
35
|
+
// Go up until we're out of node_modules
|
|
36
|
+
const parts = current.split('node_modules');
|
|
37
|
+
current = parts[0].replace(/[/\\]$/, ''); // Remove trailing slash
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return current;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate that the project root path is safe to use
|
|
45
|
+
*/
|
|
46
|
+
function validateProjectRoot(projectRoot) {
|
|
47
|
+
// Must be an absolute path
|
|
48
|
+
if (!isAbsolute(projectRoot)) {
|
|
49
|
+
debug(`Invalid path: not absolute - ${projectRoot}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Must exist
|
|
54
|
+
if (!existsSync(projectRoot)) {
|
|
55
|
+
debug(`Invalid path: does not exist - ${projectRoot}`);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Resolve to canonical path and verify it doesn't escape
|
|
60
|
+
const resolved = resolve(projectRoot);
|
|
61
|
+
if (resolved !== projectRoot && !projectRoot.startsWith(resolved)) {
|
|
62
|
+
debug(`Invalid path: resolution mismatch - ${projectRoot} vs ${resolved}`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Detect if we're in a NextSpark project (not the monorepo)
|
|
71
|
+
*/
|
|
72
|
+
function isNextSparkProject(projectRoot) {
|
|
73
|
+
// If we're in the monorepo, skip
|
|
74
|
+
const pnpmWorkspace = join(projectRoot, 'pnpm-workspace.yaml');
|
|
75
|
+
if (existsSync(pnpmWorkspace)) {
|
|
76
|
+
debug('Skipping: monorepo detected (pnpm-workspace.yaml exists)');
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check for package.json with nextspark dependency
|
|
81
|
+
const pkgPath = join(projectRoot, 'package.json');
|
|
82
|
+
if (!existsSync(pkgPath)) {
|
|
83
|
+
debug('Skipping: no package.json found');
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
89
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
90
|
+
|
|
91
|
+
const hasNextSpark = !!(deps['@nextsparkjs/core'] || deps['@nextsparkjs/cli']);
|
|
92
|
+
if (!hasNextSpark) {
|
|
93
|
+
debug('Skipping: no NextSpark dependencies found');
|
|
94
|
+
}
|
|
95
|
+
return hasNextSpark;
|
|
96
|
+
} catch {
|
|
97
|
+
debug('Skipping: failed to parse package.json');
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Check if the project has a .claude/ folder (AI workflow already set up)
|
|
104
|
+
*/
|
|
105
|
+
function hasAIWorkflowSetup(projectRoot) {
|
|
106
|
+
const hasClaudeDir = existsSync(join(projectRoot, '.claude'));
|
|
107
|
+
if (!hasClaudeDir) {
|
|
108
|
+
debug('Skipping: no .claude/ folder found (AI workflow not set up yet)');
|
|
109
|
+
}
|
|
110
|
+
return hasClaudeDir;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Find the setup.mjs script path relative to this postinstall script
|
|
115
|
+
*/
|
|
116
|
+
function getSetupScriptPath() {
|
|
117
|
+
// This script is at packages/ai-workflow/scripts/postinstall.mjs
|
|
118
|
+
// setup.mjs is at packages/ai-workflow/scripts/setup.mjs
|
|
119
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
120
|
+
const __dirname = dirname(__filename);
|
|
121
|
+
const setupPath = join(__dirname, 'setup.mjs');
|
|
122
|
+
|
|
123
|
+
if (existsSync(setupPath)) {
|
|
124
|
+
return setupPath;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
debug(`Setup script not found at ${setupPath}`);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Main execution
|
|
132
|
+
try {
|
|
133
|
+
const projectRoot = findProjectRoot();
|
|
134
|
+
debug(`Project root: ${projectRoot}`);
|
|
135
|
+
|
|
136
|
+
// Validate project root path
|
|
137
|
+
if (!validateProjectRoot(projectRoot)) {
|
|
138
|
+
debug('Skipping: invalid project root path');
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Only run in NextSpark projects with an existing .claude/ folder
|
|
143
|
+
if (isNextSparkProject(projectRoot) && hasAIWorkflowSetup(projectRoot)) {
|
|
144
|
+
console.log('\n 📦 @nextsparkjs/ai-workflow updated - syncing AI workflow files...\n');
|
|
145
|
+
|
|
146
|
+
const setupScript = getSetupScriptPath();
|
|
147
|
+
if (setupScript) {
|
|
148
|
+
try {
|
|
149
|
+
execSync(`node "${setupScript}" claude`, {
|
|
150
|
+
stdio: 'inherit',
|
|
151
|
+
cwd: projectRoot,
|
|
152
|
+
});
|
|
153
|
+
} catch (syncError) {
|
|
154
|
+
console.warn('\n ⚠️ Auto-sync failed. Run manually: npx nextspark sync:ai\n');
|
|
155
|
+
debug(`Sync error: ${syncError.message}`);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
debug('Skipping: setup.mjs script not found');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
// Postinstall hooks should not break installations
|
|
163
|
+
// The user can always run the sync manually
|
|
164
|
+
if (DEBUG) {
|
|
165
|
+
console.warn('\n [DEBUG] Postinstall error:', error.message);
|
|
166
|
+
if (error.stack) {
|
|
167
|
+
console.warn(error.stack);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|