prjct-cli 0.25.0 → 0.25.2
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/CHANGELOG.md +15 -0
- package/bin/prjct +33 -3
- package/core/infrastructure/setup.ts +51 -0
- package/package.json +1 -1
- package/templates/commands/sync.md +14 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.25.1] - 2026-01-01
|
|
4
|
+
|
|
5
|
+
### Bug Fix: npm install symlink resolution
|
|
6
|
+
|
|
7
|
+
**Fixed:** CLI fails when invoked via npm symlink (`node_modules/.bin/prjct`)
|
|
8
|
+
|
|
9
|
+
**Root Cause:**
|
|
10
|
+
The shell wrapper script `bin/prjct` used `dirname "$0"` to find `prjct.ts`, which returns the symlink's directory (`.bin/`) instead of the actual script location (`prjct-cli/bin/`).
|
|
11
|
+
|
|
12
|
+
**Solution:**
|
|
13
|
+
Added `resolve_symlink()` function that properly resolves symlinks before determining paths. Works on both Linux (`readlink -f`) and macOS (manual resolution fallback).
|
|
14
|
+
|
|
15
|
+
**Files Changed:**
|
|
16
|
+
- `bin/prjct` - Added symlink resolution (v1.0.0 → v1.1.0)
|
|
17
|
+
|
|
3
18
|
## [0.25.0] - 2025-12-30
|
|
4
19
|
|
|
5
20
|
### Maintenance Release
|
package/bin/prjct
CHANGED
|
@@ -5,10 +5,40 @@
|
|
|
5
5
|
# Detects available runtime (bun preferred, node fallback)
|
|
6
6
|
# and executes the appropriate entry point.
|
|
7
7
|
#
|
|
8
|
-
# @version 1.
|
|
8
|
+
# @version 1.1.0
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
|
|
10
|
+
# Resolve symlinks to get the actual script location
|
|
11
|
+
resolve_symlink() {
|
|
12
|
+
TARGET="$1"
|
|
13
|
+
|
|
14
|
+
# Try readlink -f (Linux, newer macOS)
|
|
15
|
+
if command -v readlink >/dev/null 2>&1; then
|
|
16
|
+
RESOLVED="$(readlink -f "$TARGET" 2>/dev/null)"
|
|
17
|
+
if [ -n "$RESOLVED" ]; then
|
|
18
|
+
echo "$RESOLVED"
|
|
19
|
+
return
|
|
20
|
+
fi
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Fallback: manual symlink resolution
|
|
24
|
+
while [ -L "$TARGET" ]; do
|
|
25
|
+
DIR="$(dirname "$TARGET")"
|
|
26
|
+
TARGET="$(readlink "$TARGET")"
|
|
27
|
+
# Handle relative symlinks
|
|
28
|
+
case "$TARGET" in
|
|
29
|
+
/*) ;;
|
|
30
|
+
*) TARGET="$DIR/$TARGET" ;;
|
|
31
|
+
esac
|
|
32
|
+
done
|
|
33
|
+
|
|
34
|
+
# Get absolute path
|
|
35
|
+
DIR="$(cd "$(dirname "$TARGET")" && pwd)"
|
|
36
|
+
echo "$DIR/$(basename "$TARGET")"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Get the actual script location (resolving symlinks)
|
|
40
|
+
SCRIPT_PATH="$(resolve_symlink "$0")"
|
|
41
|
+
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
|
|
12
42
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
13
43
|
|
|
14
44
|
# Check if bun is available
|
|
@@ -117,6 +117,9 @@ export async function run(): Promise<SetupResults> {
|
|
|
117
117
|
// Step 5: Save version in editors-config
|
|
118
118
|
await editorsConfig.saveConfig(VERSION, installer.getInstallPath())
|
|
119
119
|
|
|
120
|
+
// Step 6: Migrate existing projects to add cliVersion
|
|
121
|
+
await migrateProjectsCliVersion()
|
|
122
|
+
|
|
120
123
|
// Show results
|
|
121
124
|
showResults(results)
|
|
122
125
|
|
|
@@ -126,6 +129,54 @@ export async function run(): Promise<SetupResults> {
|
|
|
126
129
|
// Default export for CommonJS require
|
|
127
130
|
export default { run }
|
|
128
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Migrate existing projects to add cliVersion field
|
|
134
|
+
* This clears the status line warning after npm update
|
|
135
|
+
*/
|
|
136
|
+
async function migrateProjectsCliVersion(): Promise<void> {
|
|
137
|
+
try {
|
|
138
|
+
const projectsDir = path.join(os.homedir(), '.prjct-cli', 'projects')
|
|
139
|
+
|
|
140
|
+
if (!fs.existsSync(projectsDir)) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true })
|
|
145
|
+
.filter(dirent => dirent.isDirectory())
|
|
146
|
+
.map(dirent => dirent.name)
|
|
147
|
+
|
|
148
|
+
let migrated = 0
|
|
149
|
+
|
|
150
|
+
for (const projectId of projectDirs) {
|
|
151
|
+
const projectJsonPath = path.join(projectsDir, projectId, 'project.json')
|
|
152
|
+
|
|
153
|
+
if (!fs.existsSync(projectJsonPath)) {
|
|
154
|
+
continue
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const content = fs.readFileSync(projectJsonPath, 'utf8')
|
|
159
|
+
const project = JSON.parse(content)
|
|
160
|
+
|
|
161
|
+
// Only update if cliVersion is missing or different
|
|
162
|
+
if (project.cliVersion !== VERSION) {
|
|
163
|
+
project.cliVersion = VERSION
|
|
164
|
+
fs.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2))
|
|
165
|
+
migrated++
|
|
166
|
+
}
|
|
167
|
+
} catch {
|
|
168
|
+
// Skip invalid project.json files
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (migrated > 0) {
|
|
173
|
+
console.log(` ${GREEN}✓${NC} Updated ${migrated} project(s) to v${VERSION}`)
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
// Silently fail - migration is optional
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
129
180
|
/**
|
|
130
181
|
* Install status line script with version check
|
|
131
182
|
*/
|
package/package.json
CHANGED
|
@@ -383,20 +383,25 @@ WRITE: `{globalPath}/context/CLAUDE.md`
|
|
|
383
383
|
|
|
384
384
|
---
|
|
385
385
|
|
|
386
|
-
## Step 6: Update project.json
|
|
386
|
+
## Step 6: Update project.json (CRITICAL: cliVersion)
|
|
387
387
|
|
|
388
|
-
READ existing: `{globalPath}/project.json` (preserve createdAt)
|
|
388
|
+
READ existing: `{globalPath}/project.json` (preserve createdAt, integrations)
|
|
389
389
|
|
|
390
|
-
GET CLI version:
|
|
390
|
+
GET CLI version (REQUIRED - this clears the status line warning):
|
|
391
391
|
```bash
|
|
392
392
|
bun -e "console.log(require('./package.json').version)" 2>/dev/null || node -e "console.log(require('./package.json').version)"
|
|
393
393
|
```
|
|
394
|
-
SET: `{cliVersion}` = result (e.g., "0.
|
|
394
|
+
SET: `{cliVersion}` = result (e.g., "0.25.1")
|
|
395
395
|
|
|
396
396
|
CHECK: `{previousCliVersion}` = existing.cliVersion (if any)
|
|
397
|
-
SET: `{isVersionUpgrade}` = previousCliVersion != cliVersion
|
|
397
|
+
SET: `{isVersionUpgrade}` = previousCliVersion != cliVersion OR previousCliVersion is missing
|
|
398
398
|
|
|
399
|
-
|
|
399
|
+
**CRITICAL**: The `cliVersion` field MUST be written to project.json. This field:
|
|
400
|
+
- Clears the "⚠️ prjct v{version} available!" status line warning
|
|
401
|
+
- Indicates which CLI version last synced this project
|
|
402
|
+
- If missing, the warning will persist even after sync
|
|
403
|
+
|
|
404
|
+
WRITE: `{globalPath}/project.json` (merge with existing, but ALWAYS update these fields):
|
|
400
405
|
|
|
401
406
|
```json
|
|
402
407
|
{
|
|
@@ -404,7 +409,7 @@ WRITE: `{globalPath}/project.json`
|
|
|
404
409
|
"repoPath": "{cwd}",
|
|
405
410
|
"name": "{projectName}",
|
|
406
411
|
"version": "{version}",
|
|
407
|
-
"cliVersion": "{cliVersion}",
|
|
412
|
+
"cliVersion": "{cliVersion}", // ← REQUIRED: Must match CLI version to clear warning
|
|
408
413
|
"techStack": {techStack},
|
|
409
414
|
"fileCount": {fileCount},
|
|
410
415
|
"commitCount": {commitCount},
|
|
@@ -412,7 +417,8 @@ WRITE: `{globalPath}/project.json`
|
|
|
412
417
|
"currentBranch": "{currentBranch}",
|
|
413
418
|
"hasUncommittedChanges": {hasUncommittedChanges},
|
|
414
419
|
"createdAt": "{existingCreatedAt || GetTimestamp()}",
|
|
415
|
-
"lastSync": "{GetTimestamp()}"
|
|
420
|
+
"lastSync": "{GetTimestamp()}",
|
|
421
|
+
"integrations": "{existing.integrations || {}}" // ← Preserve integrations
|
|
416
422
|
}
|
|
417
423
|
```
|
|
418
424
|
|