pmpt-cli 1.2.0 → 1.2.1
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/dist/commands/import.js +152 -0
- package/dist/index.js +7 -0
- package/dist/lib/plan.js +13 -1
- package/package.json +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import { resolve, join } from 'path';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, cpSync, rmSync } from 'fs';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import { isInitialized, getConfigDir, getHistoryDir, getDocsDir, initializeProject } from '../lib/config.js';
|
|
6
|
+
/**
|
|
7
|
+
* Extract zip file
|
|
8
|
+
* Uses native unzip command on macOS/Linux, PowerShell on Windows
|
|
9
|
+
*/
|
|
10
|
+
function extractZip(zipPath, destDir) {
|
|
11
|
+
try {
|
|
12
|
+
const platform = process.platform;
|
|
13
|
+
mkdirSync(destDir, { recursive: true });
|
|
14
|
+
if (platform === 'win32') {
|
|
15
|
+
// PowerShell Expand-Archive
|
|
16
|
+
execSync(`powershell -command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`, {
|
|
17
|
+
stdio: 'pipe',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Unix unzip command
|
|
22
|
+
execSync(`unzip -o "${zipPath}" -d "${destDir}"`, {
|
|
23
|
+
stdio: 'pipe',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function cmdImport(zipFile, options) {
|
|
33
|
+
if (!zipFile) {
|
|
34
|
+
p.log.error('Please provide a zip file path.');
|
|
35
|
+
p.log.info('Usage: pmpt import <file.zip>');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const zipPath = resolve(zipFile);
|
|
39
|
+
if (!existsSync(zipPath)) {
|
|
40
|
+
p.log.error(`File not found: ${zipPath}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
if (!zipPath.endsWith('.zip')) {
|
|
44
|
+
p.log.error('Please provide a .zip file.');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
p.intro('pmpt import');
|
|
48
|
+
const projectPath = process.cwd();
|
|
49
|
+
// Check if already initialized
|
|
50
|
+
if (isInitialized(projectPath) && !options?.force) {
|
|
51
|
+
const overwrite = await p.confirm({
|
|
52
|
+
message: 'Project already initialized. Merge imported history?',
|
|
53
|
+
initialValue: true,
|
|
54
|
+
});
|
|
55
|
+
if (p.isCancel(overwrite)) {
|
|
56
|
+
p.cancel('Import cancelled.');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
if (!overwrite) {
|
|
60
|
+
p.log.info('Use --force to overwrite existing project.');
|
|
61
|
+
p.outro('');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const s = p.spinner();
|
|
66
|
+
s.start('Extracting archive...');
|
|
67
|
+
// Create temp directory for extraction
|
|
68
|
+
const tempDir = join(projectPath, '.pmpt-import-temp');
|
|
69
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
70
|
+
const extracted = extractZip(zipPath, tempDir);
|
|
71
|
+
if (!extracted) {
|
|
72
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
73
|
+
s.stop('Extraction failed');
|
|
74
|
+
p.log.error('Failed to extract zip file.');
|
|
75
|
+
p.log.info('Make sure `unzip` command is available on your system.');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
s.message('Importing project...');
|
|
79
|
+
// Read imported data
|
|
80
|
+
let importedPlan = null;
|
|
81
|
+
let importedConfig = null;
|
|
82
|
+
let projectName = 'imported-project';
|
|
83
|
+
// Read plan.json if exists
|
|
84
|
+
const planPath = join(tempDir, 'plan.json');
|
|
85
|
+
if (existsSync(planPath)) {
|
|
86
|
+
try {
|
|
87
|
+
importedPlan = JSON.parse(readFileSync(planPath, 'utf-8'));
|
|
88
|
+
if (importedPlan.answers?.projectName) {
|
|
89
|
+
projectName = importedPlan.answers.projectName;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Ignore parse errors
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Read config.json if exists
|
|
97
|
+
const configPath = join(tempDir, 'config.json');
|
|
98
|
+
if (existsSync(configPath)) {
|
|
99
|
+
try {
|
|
100
|
+
importedConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Ignore parse errors
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Initialize project if not exists
|
|
107
|
+
if (!isInitialized(projectPath)) {
|
|
108
|
+
initializeProject(projectPath, {
|
|
109
|
+
trackGit: importedConfig?.trackGit ?? true,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const pmptDir = getConfigDir(projectPath);
|
|
113
|
+
const historyDir = getHistoryDir(projectPath);
|
|
114
|
+
const docsDir = getDocsDir(projectPath);
|
|
115
|
+
// Import history
|
|
116
|
+
const importedHistoryDir = join(tempDir, 'history');
|
|
117
|
+
if (existsSync(importedHistoryDir)) {
|
|
118
|
+
// Copy all version folders
|
|
119
|
+
cpSync(importedHistoryDir, historyDir, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
// Import docs
|
|
122
|
+
const importedDocsDir = join(tempDir, 'docs');
|
|
123
|
+
if (existsSync(importedDocsDir)) {
|
|
124
|
+
cpSync(importedDocsDir, docsDir, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
// Import plan progress
|
|
127
|
+
if (importedPlan) {
|
|
128
|
+
const planProgressPath = join(pmptDir, 'plan-progress.json');
|
|
129
|
+
writeFileSync(planProgressPath, JSON.stringify(importedPlan, null, 2), 'utf-8');
|
|
130
|
+
}
|
|
131
|
+
// Count imported versions
|
|
132
|
+
let versionCount = 0;
|
|
133
|
+
if (existsSync(historyDir)) {
|
|
134
|
+
const { readdirSync } = await import('fs');
|
|
135
|
+
versionCount = readdirSync(historyDir).filter(d => d.startsWith('v')).length;
|
|
136
|
+
}
|
|
137
|
+
// Cleanup temp directory
|
|
138
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
139
|
+
s.stop('Import complete!');
|
|
140
|
+
// Summary
|
|
141
|
+
const summary = [
|
|
142
|
+
`Project: ${projectName}`,
|
|
143
|
+
`Versions imported: ${versionCount}`,
|
|
144
|
+
`Location: ${pmptDir}`,
|
|
145
|
+
];
|
|
146
|
+
p.note(summary.join('\n'), 'Import Summary');
|
|
147
|
+
p.log.info('Next steps:');
|
|
148
|
+
p.log.message(' pmpt history — View imported versions');
|
|
149
|
+
p.log.message(' pmpt plan — View or copy AI prompt');
|
|
150
|
+
p.log.message(' pmpt save — Save a new snapshot');
|
|
151
|
+
p.outro('Ready to continue the journey!');
|
|
152
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { cmdPlan } from './commands/plan.js';
|
|
|
11
11
|
import { cmdSave } from './commands/save.js';
|
|
12
12
|
import { cmdSquash } from './commands/squash.js';
|
|
13
13
|
import { cmdExport } from './commands/export.js';
|
|
14
|
+
import { cmdImport } from './commands/import.js';
|
|
14
15
|
const program = new Command();
|
|
15
16
|
program
|
|
16
17
|
.name('pmpt')
|
|
@@ -26,6 +27,7 @@ Examples:
|
|
|
26
27
|
$ pmpt history --compact Hide minor changes
|
|
27
28
|
$ pmpt squash v2 v5 Merge versions v2-v5 into v2
|
|
28
29
|
$ pmpt export Export history as shareable zip
|
|
30
|
+
$ pmpt import <file.zip> Import project from zip
|
|
29
31
|
|
|
30
32
|
Folder structure:
|
|
31
33
|
.pmpt/
|
|
@@ -67,6 +69,11 @@ program
|
|
|
67
69
|
.description('Export project history as a shareable zip archive')
|
|
68
70
|
.option('-o, --output <file>', 'Output file path')
|
|
69
71
|
.action(cmdExport);
|
|
72
|
+
program
|
|
73
|
+
.command('import <file>')
|
|
74
|
+
.description('Import project from exported zip archive')
|
|
75
|
+
.option('-f, --force', 'Overwrite existing project')
|
|
76
|
+
.action(cmdImport);
|
|
70
77
|
program
|
|
71
78
|
.command('plan [path]')
|
|
72
79
|
.description('Quick product planning with 5 questions — auto-generate AI prompt')
|
package/dist/lib/plan.js
CHANGED
|
@@ -90,7 +90,19 @@ Add a "## Progress" section below and keep it updated:
|
|
|
90
90
|
- [ ] Pending item
|
|
91
91
|
\`\`\`
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
Also, add a "## Snapshot Log" section to record what was built at each checkpoint:
|
|
94
|
+
\`\`\`
|
|
95
|
+
## Snapshot Log
|
|
96
|
+
### v1 - Initial Setup
|
|
97
|
+
- Set up project structure
|
|
98
|
+
- Installed dependencies: React, Tailwind
|
|
99
|
+
|
|
100
|
+
### v2 - Auth Feature
|
|
101
|
+
- Implemented login/signup
|
|
102
|
+
- Added JWT authentication
|
|
103
|
+
\`\`\`
|
|
104
|
+
|
|
105
|
+
This helps others understand what was built at each version when they import this project.
|
|
94
106
|
`;
|
|
95
107
|
}
|
|
96
108
|
// Generate plan document
|