@baseplate-dev/project-builder-cli 0.2.5 → 0.3.0
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/diff.js +1 -1
- package/dist/commands/snapshot.d.ts +6 -0
- package/dist/commands/snapshot.js +121 -0
- package/dist/commands/sync.js +10 -2
- package/dist/index.js +2 -0
- package/package.json +13 -13
package/dist/commands/diff.js
CHANGED
|
@@ -9,7 +9,7 @@ import { logger } from '../services/logger.js';
|
|
|
9
9
|
export function addDiffCommand(program) {
|
|
10
10
|
program
|
|
11
11
|
.command('diff [directory]')
|
|
12
|
-
.description('
|
|
12
|
+
.description('Show diff between generated output and current working directory')
|
|
13
13
|
.option('--compact', 'Show compact diff format instead of unified diff')
|
|
14
14
|
.option('--app <apps...>', 'Filter by specific app names')
|
|
15
15
|
.option('--glob <patterns...>', 'Filter files by glob patterns')
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { createSchemaParserContext } from '#src/services/schema-parser-context.js';
|
|
3
|
+
import { getUserConfig } from '#src/services/user-config.js';
|
|
4
|
+
import { expandPathWithTilde } from '#src/utils/path.js';
|
|
5
|
+
import { logger } from '../services/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Adds snapshot management commands to the program.
|
|
8
|
+
* @param program - The program to add the command to.
|
|
9
|
+
*/
|
|
10
|
+
export function addSnapshotCommand(program) {
|
|
11
|
+
const snapshotCommand = program
|
|
12
|
+
.command('snapshot')
|
|
13
|
+
.description('Manage project snapshots for persistent differences');
|
|
14
|
+
// snapshot add command
|
|
15
|
+
snapshotCommand
|
|
16
|
+
.command('add <project-directory> <app> <files...>')
|
|
17
|
+
.description('Add files to snapshot (use --deleted for intentionally deleted files)')
|
|
18
|
+
.option('--deleted', 'Mark files as intentionally deleted in snapshot')
|
|
19
|
+
.option('--snapshot-dir <directory>', 'Snapshot directory', '.baseplate-snapshot')
|
|
20
|
+
.action(async (projectDirectory, app, files, options) => {
|
|
21
|
+
try {
|
|
22
|
+
const { addFilesToSnapshot } = await import('@baseplate-dev/project-builder-server');
|
|
23
|
+
const resolvedDirectory = expandPathWithTilde(projectDirectory);
|
|
24
|
+
const context = await createSchemaParserContext(resolvedDirectory);
|
|
25
|
+
await addFilesToSnapshot(files, !!options.deleted, {
|
|
26
|
+
projectDirectory: resolvedDirectory,
|
|
27
|
+
snapshotDirectory: options.snapshotDir,
|
|
28
|
+
appName: app,
|
|
29
|
+
context,
|
|
30
|
+
logger,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logger.error('Failed to add files to snapshot:', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// snapshot remove command
|
|
39
|
+
snapshotCommand
|
|
40
|
+
.command('remove <project-directory> <app> <files...>')
|
|
41
|
+
.description('Remove files from snapshot tracking')
|
|
42
|
+
.option('--snapshot-dir <directory>', 'Snapshot directory', '.baseplate-snapshot')
|
|
43
|
+
.action(async (projectDirectory, app, files, options) => {
|
|
44
|
+
try {
|
|
45
|
+
const { removeFilesFromSnapshot } = await import('@baseplate-dev/project-builder-server');
|
|
46
|
+
const resolvedDirectory = expandPathWithTilde(projectDirectory);
|
|
47
|
+
const context = await createSchemaParserContext(resolvedDirectory);
|
|
48
|
+
await removeFilesFromSnapshot(files, {
|
|
49
|
+
projectDirectory: resolvedDirectory,
|
|
50
|
+
snapshotDirectory: options.snapshotDir,
|
|
51
|
+
appName: app,
|
|
52
|
+
context,
|
|
53
|
+
logger,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logger.error('Failed to remove files from snapshot:', error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// snapshot save command
|
|
62
|
+
snapshotCommand
|
|
63
|
+
.command('save <project-directory> <app>')
|
|
64
|
+
.description('Save snapshot of current differences (overwrites existing snapshot)')
|
|
65
|
+
.option('--snapshot-dir <directory>', 'Snapshot directory', '.baseplate-snapshot')
|
|
66
|
+
.action(async (projectDirectory, app, options) => {
|
|
67
|
+
try {
|
|
68
|
+
const { createSnapshotForProject } = await import('@baseplate-dev/project-builder-server');
|
|
69
|
+
const resolvedDirectory = expandPathWithTilde(projectDirectory);
|
|
70
|
+
const context = await createSchemaParserContext(resolvedDirectory);
|
|
71
|
+
const userConfig = await getUserConfig();
|
|
72
|
+
// Confirm with user before overwriting existing snapshot
|
|
73
|
+
console.warn('⚠️ This will overwrite any existing snapshot for this app.');
|
|
74
|
+
console.info('Use granular commands (snapshot add/remove) for safer updates.');
|
|
75
|
+
const proceed = await confirm({
|
|
76
|
+
message: 'Are you sure you want to overwrite the existing snapshot?',
|
|
77
|
+
default: false,
|
|
78
|
+
});
|
|
79
|
+
if (!proceed) {
|
|
80
|
+
logger.info('Aborted snapshot save.');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
await createSnapshotForProject({
|
|
84
|
+
projectDirectory: resolvedDirectory,
|
|
85
|
+
app,
|
|
86
|
+
logger,
|
|
87
|
+
context,
|
|
88
|
+
userConfig,
|
|
89
|
+
snapshotDir: options.snapshotDir,
|
|
90
|
+
});
|
|
91
|
+
logger.info('✅ Snapshot saved successfully');
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
logger.error('Failed to save snapshot:', error);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
// snapshot show command
|
|
99
|
+
snapshotCommand
|
|
100
|
+
.command('show <project-directory> <app>')
|
|
101
|
+
.description('Show current snapshot contents')
|
|
102
|
+
.option('--snapshot-dir <directory>', 'Snapshot directory', '.baseplate-snapshot')
|
|
103
|
+
.action(async (projectDirectory, app, options) => {
|
|
104
|
+
try {
|
|
105
|
+
const { listSnapshotContents } = await import('@baseplate-dev/project-builder-server');
|
|
106
|
+
const resolvedDirectory = expandPathWithTilde(projectDirectory);
|
|
107
|
+
const context = await createSchemaParserContext(resolvedDirectory);
|
|
108
|
+
await listSnapshotContents({
|
|
109
|
+
projectDirectory: resolvedDirectory,
|
|
110
|
+
appName: app,
|
|
111
|
+
snapshotDirectory: options.snapshotDir,
|
|
112
|
+
context,
|
|
113
|
+
logger,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.error('Failed to show snapshot contents:', error);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
package/dist/commands/sync.js
CHANGED
|
@@ -10,12 +10,19 @@ export function addSyncCommand(program) {
|
|
|
10
10
|
program
|
|
11
11
|
.command('sync [directory]')
|
|
12
12
|
.description('Syncs project from project-definition.json in baseplate/ directory')
|
|
13
|
-
.option('--
|
|
13
|
+
.option('--overwrite', 'Force overwrite existing files and apply snapshots automatically')
|
|
14
|
+
.option('--snapshot <directory>', 'Apply diffs from snapshot directory (requires --overwrite)')
|
|
14
15
|
.action(async (directory, options) => {
|
|
15
16
|
const { syncProject, SyncMetadataController } = await import('@baseplate-dev/project-builder-server');
|
|
16
17
|
const resolvedDirectory = directory
|
|
17
18
|
? expandPathWithTilde(directory)
|
|
18
19
|
: '.';
|
|
20
|
+
// Validate that --snapshot requires --overwrite
|
|
21
|
+
if (options.snapshot && !options.overwrite) {
|
|
22
|
+
logger.error('Error: --snapshot option requires --overwrite flag');
|
|
23
|
+
logger.error('Snapshots are only applied when overwriting files, not during normal merging.');
|
|
24
|
+
throw new Error('--snapshot option requires --overwrite flag');
|
|
25
|
+
}
|
|
19
26
|
const context = await createSchemaParserContext(resolvedDirectory);
|
|
20
27
|
const userConfig = await getUserConfig();
|
|
21
28
|
const syncMetadataController = new SyncMetadataController(resolvedDirectory, logger);
|
|
@@ -27,7 +34,8 @@ export function addSyncCommand(program) {
|
|
|
27
34
|
userConfig,
|
|
28
35
|
cliFilePath: process.argv[1],
|
|
29
36
|
syncMetadataController,
|
|
30
|
-
|
|
37
|
+
overwrite: options.overwrite ?? false,
|
|
38
|
+
snapshotDirectory: options.overwrite ? options.snapshot : undefined,
|
|
31
39
|
});
|
|
32
40
|
}
|
|
33
41
|
catch (error) {
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { program } from 'commander';
|
|
|
2
2
|
import { addConfigCommand } from './commands/config.js';
|
|
3
3
|
import { addDiffCommand } from './commands/diff.js';
|
|
4
4
|
import { addServeCommand } from './commands/server.js';
|
|
5
|
+
import { addSnapshotCommand } from './commands/snapshot.js';
|
|
5
6
|
import { addSyncCommand } from './commands/sync.js';
|
|
6
7
|
import { addTemplatesCommand } from './commands/templates.js';
|
|
7
8
|
import { getEnabledFeatureFlags } from './services/feature-flags.js';
|
|
@@ -16,6 +17,7 @@ export async function runCli() {
|
|
|
16
17
|
program.version(version, '-v, --version');
|
|
17
18
|
if (enabledFlags.includes('TEMPLATE_EXTRACTOR')) {
|
|
18
19
|
addTemplatesCommand(program);
|
|
20
|
+
addSnapshotCommand(program);
|
|
19
21
|
}
|
|
20
22
|
addSyncCommand(program);
|
|
21
23
|
addDiffCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baseplate-dev/project-builder-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Full-stack CLI builder using Baseplate generators",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -40,28 +40,28 @@
|
|
|
40
40
|
"bin/**/*"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@inquirer/prompts": "7.2.1",
|
|
43
44
|
"commander": "^12.1.0",
|
|
44
45
|
"pino": "9.5.0",
|
|
45
46
|
"pino-pretty": "13.0.0",
|
|
46
47
|
"pkg-dir": "^8.0.0",
|
|
47
48
|
"zod": "3.24.1",
|
|
48
|
-
"@baseplate-dev/project-builder-common": "0.
|
|
49
|
-
"@baseplate-dev/project-builder-lib": "0.
|
|
50
|
-
"@baseplate-dev/project-builder-server": "0.
|
|
51
|
-
"@baseplate-dev/project-builder-web": "0.
|
|
52
|
-
"@baseplate-dev/utils": "0.
|
|
49
|
+
"@baseplate-dev/project-builder-common": "0.3.0",
|
|
50
|
+
"@baseplate-dev/project-builder-lib": "0.3.0",
|
|
51
|
+
"@baseplate-dev/project-builder-server": "0.3.0",
|
|
52
|
+
"@baseplate-dev/project-builder-web": "0.3.0",
|
|
53
|
+
"@baseplate-dev/utils": "0.3.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@playwright/test": "1.51.0",
|
|
56
57
|
"@types/node": "^22.0.0",
|
|
57
|
-
"
|
|
58
|
-
"eslint": "9.26.0",
|
|
58
|
+
"eslint": "9.32.0",
|
|
59
59
|
"fastify": "5.3.2",
|
|
60
|
-
"prettier": "3.
|
|
60
|
+
"prettier": "3.6.2",
|
|
61
61
|
"tsx": "4.19.3",
|
|
62
62
|
"typescript": "5.7.3",
|
|
63
|
-
"vitest": "3.
|
|
64
|
-
"@baseplate-dev/tools": "0.
|
|
63
|
+
"vitest": "3.2.4",
|
|
64
|
+
"@baseplate-dev/tools": "0.3.0"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
67
|
"node": "^22.0.0"
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build": "tsc -p tsconfig.build.json",
|
|
78
78
|
"clean": "rm -rf ./dist",
|
|
79
|
-
"dev": "tsx watch --tsconfig ./tsconfig.app.json --exclude /**/node_modules/** -
|
|
79
|
+
"dev": "tsx watch --tsconfig ./tsconfig.app.json --exclude /**/node_modules/** --env-file-if-exists=.env -C development ./src/cli.ts",
|
|
80
80
|
"dev:serve": "pnpm dev serve",
|
|
81
81
|
"lint": "eslint .",
|
|
82
82
|
"prettier:check": "prettier --check .",
|
|
83
83
|
"prettier:write": "prettier -w .",
|
|
84
84
|
"project:generate": "pnpm start generate",
|
|
85
|
-
"start": "tsx --tsconfig ./tsconfig.app.json -
|
|
85
|
+
"start": "tsx --tsconfig ./tsconfig.app.json --env-file-if-exists=.env -C development ./src/cli.ts",
|
|
86
86
|
"templates:extract": "pnpm start templates extract",
|
|
87
87
|
"templates:generate": "pnpm start templates generate",
|
|
88
88
|
"test": "vitest",
|