blok0 0.1.0 โ 0.1.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/api/index.d.ts +46 -0
- package/dist/api/index.js +147 -0
- package/dist/ast/index.d.ts +31 -0
- package/dist/ast/index.js +324 -0
- package/dist/auth/constants.d.ts +11 -0
- package/dist/auth/constants.js +155 -0
- package/dist/auth/index.d.ts +61 -0
- package/dist/auth/index.js +168 -0
- package/dist/auth/server.d.ts +55 -0
- package/dist/auth/server.js +236 -0
- package/dist/blocks/index.d.ts +56 -0
- package/dist/blocks/index.js +189 -0
- package/dist/handlers/add-block.d.ts +7 -0
- package/dist/handlers/add-block.js +142 -0
- package/dist/handlers/login.d.ts +8 -0
- package/dist/handlers/login.js +124 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +187 -7
- package/dist/registry/index.d.ts +75 -0
- package/dist/registry/index.js +231 -0
- package/package.json +33 -25
- package/src/api/index.ts +177 -0
- package/src/ast/index.ts +368 -0
- package/src/auth/constants.ts +155 -0
- package/src/auth/index.ts +154 -0
- package/src/auth/server.ts +240 -0
- package/src/blocks/index.ts +186 -0
- package/src/detectors.ts +22 -22
- package/src/handlers/add-block.ts +132 -0
- package/src/handlers/generate.ts +62 -62
- package/src/handlers/login.ts +130 -0
- package/src/index.ts +212 -51
- package/src/registry/index.ts +244 -0
- package/test-ast.js +150 -0
- package/tsconfig.json +16 -16
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { isAuthenticated } from '../auth';
|
|
3
|
+
import { apiClient } from '../api';
|
|
4
|
+
import { isBlockRegistered, addBlockToRegistry, calculateDirectoryChecksums } from '../registry';
|
|
5
|
+
import {
|
|
6
|
+
ensureBlocksDirectory,
|
|
7
|
+
createBlockDirectory,
|
|
8
|
+
createBlockEntry,
|
|
9
|
+
slugToIdentifier,
|
|
10
|
+
validateBlockDirectory
|
|
11
|
+
} from '../blocks';
|
|
12
|
+
import { updatePageCollectionConfig, updateRenderBlocksComponent, findPagesCollection, findRenderBlocksComponent } from '../ast';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handle add block command
|
|
16
|
+
*/
|
|
17
|
+
export async function handleAddBlock(blockUrl: string, options: { force?: boolean; dryRun?: boolean } = {}): Promise<void> {
|
|
18
|
+
console.log('๐ฆ Adding Blok0 Block');
|
|
19
|
+
console.log('====================');
|
|
20
|
+
console.log('');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Step 1: Authentication check
|
|
24
|
+
console.log('๐ Checking authentication...');
|
|
25
|
+
const authenticated = await isAuthenticated();
|
|
26
|
+
if (!authenticated) {
|
|
27
|
+
console.error('โ You are not logged in. Please run `blok0 login` first.');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Step 2: Fetch block data from API
|
|
32
|
+
console.log(`๐ก Fetching block from: ${blockUrl}`);
|
|
33
|
+
const { metadata, files } = await apiClient.fetchBlockData(blockUrl);
|
|
34
|
+
console.log(`โ
Found block: "${metadata.name}" (${metadata.slug})`);
|
|
35
|
+
|
|
36
|
+
// Step 3: Check if block is already registered
|
|
37
|
+
if (isBlockRegistered(metadata.slug)) {
|
|
38
|
+
if (!options.force) {
|
|
39
|
+
console.error(`โ Block "${metadata.slug}" is already installed. Use --force to reinstall.`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.log('โ ๏ธ Block already exists, reinstalling...');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.dryRun) {
|
|
46
|
+
console.log('๐ Dry run mode - would perform the following actions:');
|
|
47
|
+
console.log(` - Create directory: src/blocks/${metadata.slug}`);
|
|
48
|
+
console.log(` - Download ${files.length} files`);
|
|
49
|
+
console.log(' - Update Payload config');
|
|
50
|
+
console.log(' - Update RenderBlocks component');
|
|
51
|
+
console.log(' - Register block in blok0-registry.json');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Step 4: Ensure blocks directory exists
|
|
56
|
+
const blocksDir = ensureBlocksDirectory();
|
|
57
|
+
|
|
58
|
+
// Step 5: Create block directory and files
|
|
59
|
+
console.log('๐ Creating block directory and files...');
|
|
60
|
+
const { dir, configPath, componentPath } = createBlockDirectory(blocksDir, metadata.slug, files);
|
|
61
|
+
console.log(`โ
Created block directory: ${path.relative(process.cwd(), dir)}`);
|
|
62
|
+
|
|
63
|
+
// Step 6: Validate created block
|
|
64
|
+
const validation = validateBlockDirectory(dir);
|
|
65
|
+
if (!validation.valid) {
|
|
66
|
+
console.error('โ Block validation failed:');
|
|
67
|
+
validation.errors.forEach(error => console.error(` - ${error}`));
|
|
68
|
+
// Cleanup on failure
|
|
69
|
+
require('fs').rmSync(dir, { recursive: true, force: true });
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Step 7: Calculate checksums
|
|
74
|
+
const checksums = calculateDirectoryChecksums(dir);
|
|
75
|
+
|
|
76
|
+
// Step 8: Create registry entry
|
|
77
|
+
const blockEntry = createBlockEntry(
|
|
78
|
+
{
|
|
79
|
+
id: metadata.id,
|
|
80
|
+
name: metadata.name,
|
|
81
|
+
slug: metadata.slug,
|
|
82
|
+
sourceUrl: blockUrl
|
|
83
|
+
},
|
|
84
|
+
dir,
|
|
85
|
+
configPath,
|
|
86
|
+
componentPath,
|
|
87
|
+
checksums
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Step 9: Update Pages collection (AST manipulation)
|
|
91
|
+
const pagesCollectionPath = findPagesCollection();
|
|
92
|
+
if (pagesCollectionPath) {
|
|
93
|
+
console.log('๐ง Updating Pages collection...');
|
|
94
|
+
const blockIdentifier = slugToIdentifier(metadata.slug);
|
|
95
|
+
const relativeConfigPath = `@/blocks/${metadata.slug}/config`;
|
|
96
|
+
|
|
97
|
+
updatePageCollectionConfig(pagesCollectionPath, relativeConfigPath, blockIdentifier);
|
|
98
|
+
console.log(`โ
Added ${blockIdentifier} to Pages collection`);
|
|
99
|
+
} else {
|
|
100
|
+
console.warn('โ ๏ธ Could not find Pages collection file. You may need to manually add the block to your collections.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Step 10: Update RenderBlocks component (AST manipulation)
|
|
104
|
+
const renderBlocksPath = findRenderBlocksComponent();
|
|
105
|
+
if (renderBlocksPath) {
|
|
106
|
+
console.log('๐ง Updating RenderBlocks component...');
|
|
107
|
+
const relativeComponentPath = `./${metadata.slug}/Component`;
|
|
108
|
+
|
|
109
|
+
updateRenderBlocksComponent(renderBlocksPath, metadata.slug, relativeComponentPath);
|
|
110
|
+
console.log(`โ
Added ${metadata.slug} component to RenderBlocks`);
|
|
111
|
+
} else {
|
|
112
|
+
console.warn('โ ๏ธ Could not find RenderBlocks component. You may need to manually add the block component.');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Step 11: Register block in registry
|
|
116
|
+
console.log('๐ Registering block...');
|
|
117
|
+
addBlockToRegistry(blockEntry);
|
|
118
|
+
console.log('โ
Block registered successfully');
|
|
119
|
+
|
|
120
|
+
console.log('');
|
|
121
|
+
console.log('๐ Block installation complete!');
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log('Next steps:');
|
|
124
|
+
console.log('1. Review the installed files in src/blocks/' + metadata.slug);
|
|
125
|
+
console.log('2. Test your application to ensure the block works correctly');
|
|
126
|
+
console.log('3. Commit the changes to your repository');
|
|
127
|
+
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error('โ Failed to add block:', (error as Error).message);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
package/src/handlers/generate.ts
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { createInterface } from 'readline';
|
|
2
|
-
import { exec, spawn } from 'child_process';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
|
-
|
|
5
|
-
const execAsync = promisify(exec);
|
|
6
|
-
|
|
7
|
-
const repoUrl = 'https://github.com/blok0-payload/starter.git';
|
|
8
|
-
|
|
9
|
-
function prompt(question: string): Promise<boolean> {
|
|
10
|
-
return new Promise((resolve) => {
|
|
11
|
-
const rl = createInterface({
|
|
12
|
-
input: process.stdin,
|
|
13
|
-
output: process.stdout,
|
|
14
|
-
});
|
|
15
|
-
rl.question(question, (answer) => {
|
|
16
|
-
rl.close();
|
|
17
|
-
resolve(answer.toLowerCase().startsWith('y'));
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function generateStarter(): Promise<void> {
|
|
23
|
-
console.log('Cloning starter repository...');
|
|
24
|
-
try {
|
|
25
|
-
await execAsync(`git clone --depth 1 ${repoUrl} .`);
|
|
26
|
-
console.log('Repository cloned successfully.');
|
|
27
|
-
} catch (error) {
|
|
28
|
-
throw new Error(`Failed to clone repository: ${error}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Prompt for bun install
|
|
32
|
-
const installDeps = await prompt('Run \'bun install\' to install dependencies? (y/n): ');
|
|
33
|
-
if (installDeps) {
|
|
34
|
-
console.log('Installing dependencies...');
|
|
35
|
-
try {
|
|
36
|
-
await new Promise<void>((resolve, reject) => {
|
|
37
|
-
const child = spawn('bun', ['install'], { stdio: 'inherit' });
|
|
38
|
-
child.on('close', (code) => {
|
|
39
|
-
if (code === 0) resolve();
|
|
40
|
-
else reject(new Error('Failed to install dependencies'));
|
|
41
|
-
});
|
|
42
|
-
child.on('error', reject);
|
|
43
|
-
});
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('Failed to install dependencies:', error);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Prompt for git init
|
|
50
|
-
const initGit = await prompt('Initialize git repository? (y/n): ');
|
|
51
|
-
if (initGit) {
|
|
52
|
-
console.log('Initializing git repository...');
|
|
53
|
-
try {
|
|
54
|
-
await execAsync('git init');
|
|
55
|
-
console.log('Git repository initialized.');
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error('Failed to initialize git:', error);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
console.log('Blok0 starter project created successfully!');
|
|
62
|
-
}
|
|
1
|
+
import { createInterface } from 'readline';
|
|
2
|
+
import { exec, spawn } from 'child_process';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
|
|
7
|
+
const repoUrl = 'https://github.com/blok0-payload/starter.git';
|
|
8
|
+
|
|
9
|
+
function prompt(question: string): Promise<boolean> {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const rl = createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout,
|
|
14
|
+
});
|
|
15
|
+
rl.question(question, (answer) => {
|
|
16
|
+
rl.close();
|
|
17
|
+
resolve(answer.toLowerCase().startsWith('y'));
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function generateStarter(): Promise<void> {
|
|
23
|
+
console.log('Cloning starter repository...');
|
|
24
|
+
try {
|
|
25
|
+
await execAsync(`git clone --depth 1 ${repoUrl} .`);
|
|
26
|
+
console.log('Repository cloned successfully.');
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(`Failed to clone repository: ${error}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Prompt for bun install
|
|
32
|
+
const installDeps = await prompt('Run \'bun install\' to install dependencies? (y/n): ');
|
|
33
|
+
if (installDeps) {
|
|
34
|
+
console.log('Installing dependencies...');
|
|
35
|
+
try {
|
|
36
|
+
await new Promise<void>((resolve, reject) => {
|
|
37
|
+
const child = spawn('bun', ['install'], { stdio: 'inherit' });
|
|
38
|
+
child.on('close', (code) => {
|
|
39
|
+
if (code === 0) resolve();
|
|
40
|
+
else reject(new Error('Failed to install dependencies'));
|
|
41
|
+
});
|
|
42
|
+
child.on('error', reject);
|
|
43
|
+
});
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Failed to install dependencies:', error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Prompt for git init
|
|
50
|
+
const initGit = await prompt('Initialize git repository? (y/n): ');
|
|
51
|
+
if (initGit) {
|
|
52
|
+
console.log('Initializing git repository...');
|
|
53
|
+
try {
|
|
54
|
+
await execAsync('git init');
|
|
55
|
+
console.log('Git repository initialized.');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to initialize git:', error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log('Blok0 starter project created successfully!');
|
|
62
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { isAuthenticated, clearCredentials, storeAccessToken, AuthCallback } from '../auth';
|
|
2
|
+
import { AuthServer } from '../auth/server';
|
|
3
|
+
import open from 'open';
|
|
4
|
+
|
|
5
|
+
// Add SIGINT handler for graceful cleanup
|
|
6
|
+
process.on('SIGINT', () => {
|
|
7
|
+
console.log('\n\nโ ๏ธ Authentication cancelled by user.');
|
|
8
|
+
process.exit(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Handle login command
|
|
13
|
+
*/
|
|
14
|
+
export async function handleLogin(token?: string, manual?: boolean): Promise<void> {
|
|
15
|
+
// Direct token authentication (CI/CD)
|
|
16
|
+
if (token) {
|
|
17
|
+
try {
|
|
18
|
+
console.log('๐ Saving authentication token...');
|
|
19
|
+
await storeAccessToken(token);
|
|
20
|
+
console.log('โ
Successfully authenticated!');
|
|
21
|
+
console.log('');
|
|
22
|
+
console.log('You can now use blok0 commands that require authentication.');
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error('โ Failed to save authentication token:', (error as Error).message);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Manual authentication instructions
|
|
31
|
+
if (manual) {
|
|
32
|
+
showManualInstructions();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default: Browser-based authentication
|
|
37
|
+
try {
|
|
38
|
+
await handleBrowserLogin();
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('โ Browser authentication failed:', (error as Error).message);
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log('๐ก Try manual authentication:');
|
|
43
|
+
console.log(' blok0 login --manual');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Handle browser-based authentication flow
|
|
50
|
+
*/
|
|
51
|
+
async function handleBrowserLogin(): Promise<void> {
|
|
52
|
+
console.log('๐ Blok0 Authentication');
|
|
53
|
+
console.log('======================');
|
|
54
|
+
console.log('');
|
|
55
|
+
|
|
56
|
+
// Create authentication server
|
|
57
|
+
const authServer = new AuthServer();
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
// Initialize server (find available port)
|
|
61
|
+
console.log('๐ Starting authentication server...');
|
|
62
|
+
await authServer.initialize();
|
|
63
|
+
|
|
64
|
+
// Get the authorization URL (now port is available)
|
|
65
|
+
const authUrl = authServer.getAuthorizationUrl();
|
|
66
|
+
|
|
67
|
+
console.log('๐ Opening browser for authentication...');
|
|
68
|
+
await open(authUrl);
|
|
69
|
+
|
|
70
|
+
console.log('๐ฑ Please complete authentication in your browser.');
|
|
71
|
+
console.log('โณ Waiting for authentication to complete...');
|
|
72
|
+
|
|
73
|
+
// Start server and wait for callback
|
|
74
|
+
const authCallback: AuthCallback = await authServer.start();
|
|
75
|
+
|
|
76
|
+
// Store the token
|
|
77
|
+
console.log('๐ Saving authentication token...');
|
|
78
|
+
await storeAccessToken(authCallback.token);
|
|
79
|
+
console.log('โ
Successfully authenticated!');
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log('You can now use blok0 commands that require authentication.');
|
|
82
|
+
|
|
83
|
+
} catch (error) {
|
|
84
|
+
authServer.stop();
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Show manual authentication instructions
|
|
91
|
+
*/
|
|
92
|
+
function showManualInstructions(): void {
|
|
93
|
+
console.log('๐ Blok0 Manual Authentication');
|
|
94
|
+
console.log('==============================');
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log('To authenticate with the Blok0 API, make a POST request to:');
|
|
97
|
+
console.log('https://www.blok0.xyz/api/customers/login');
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log('Example using curl:');
|
|
100
|
+
console.log('curl -X POST https://www.blok0.xyz/api/customers/login \\');
|
|
101
|
+
console.log(' -H "Content-Type: application/json" \\');
|
|
102
|
+
console.log(' -d \'{"email": "your-email@example.com", "password": "your-password"}\'');
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log('Then copy the access token and run:');
|
|
105
|
+
console.log('blok0 login --token <your-token>');
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('For CI/CD environments, set the BLOK0_TOKEN environment variable.');
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log('๐ก For browser-based login, run: blok0 login');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Handle logout command
|
|
114
|
+
*/
|
|
115
|
+
export async function handleLogout(): Promise<void> {
|
|
116
|
+
try {
|
|
117
|
+
const wasAuthenticated = await isAuthenticated();
|
|
118
|
+
|
|
119
|
+
if (!wasAuthenticated) {
|
|
120
|
+
console.log('You are not currently logged in.');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
await clearCredentials();
|
|
125
|
+
console.log('โ
Successfully logged out and cleared stored credentials.');
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('โ Failed to logout:', (error as Error).message);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,51 +1,212 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
|
|
3
|
-
import { mkdirSync } from 'fs';
|
|
4
|
-
import { createInterface } from 'readline';
|
|
5
|
-
import { checkEmptyDirectory } from './detectors';
|
|
6
|
-
import { generateStarter } from './handlers/generate';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { mkdirSync } from 'fs';
|
|
4
|
+
import { createInterface } from 'readline';
|
|
5
|
+
import { checkEmptyDirectory } from './detectors';
|
|
6
|
+
import { generateStarter } from './handlers/generate';
|
|
7
|
+
import { handleLogin, handleLogout } from './handlers/login';
|
|
8
|
+
import { handleAddBlock } from './handlers/add-block';
|
|
9
|
+
import { createEmptyRegistry } from './registry';
|
|
10
|
+
|
|
11
|
+
function prompt(question: string): Promise<string> {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const rl = createInterface({
|
|
14
|
+
input: process.stdin,
|
|
15
|
+
output: process.stdout,
|
|
16
|
+
});
|
|
17
|
+
rl.question(question, (answer) => {
|
|
18
|
+
rl.close();
|
|
19
|
+
resolve(answer.trim());
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function showHelp() {
|
|
25
|
+
console.log(`
|
|
26
|
+
Blok0 - PayloadCMS Block Management CLI
|
|
27
|
+
|
|
28
|
+
USAGE:
|
|
29
|
+
blok0 <command> [subcommand] [options]
|
|
30
|
+
|
|
31
|
+
COMMANDS:
|
|
32
|
+
login Authenticate via browser or token
|
|
33
|
+
logout Remove stored credentials
|
|
34
|
+
debug Show authentication debug info
|
|
35
|
+
generate starter [folder] Generate PayloadCMS starter project
|
|
36
|
+
add block <url> Add a block from remote API
|
|
37
|
+
update block <id> Update existing block (future)
|
|
38
|
+
remove block <id> Remove block and clean up (future)
|
|
39
|
+
registry validate Validate registry integrity (future)
|
|
40
|
+
|
|
41
|
+
OPTIONS:
|
|
42
|
+
--help, -h Show this help message
|
|
43
|
+
--version, -v Show version information
|
|
44
|
+
--verbose Enable verbose logging
|
|
45
|
+
--dry-run Preview changes without applying them
|
|
46
|
+
|
|
47
|
+
EXAMPLES:
|
|
48
|
+
blok0 login
|
|
49
|
+
blok0 generate starter my-project
|
|
50
|
+
blok0 add block https://api.example.com/blocks/123
|
|
51
|
+
|
|
52
|
+
For more information, visit: https://github.com/blok0-payload/cli
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function main() {
|
|
57
|
+
const args = process.argv.slice(2);
|
|
58
|
+
|
|
59
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
60
|
+
showHelp();
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
65
|
+
const pkg = require('../package.json');
|
|
66
|
+
console.log(`blok0 v${pkg.version}`);
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const [command, ...restArgs] = args;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
switch (command) {
|
|
74
|
+
case 'generate':
|
|
75
|
+
const [genSubcommand, ...genRestArgs] = restArgs;
|
|
76
|
+
if (genSubcommand === 'starter') {
|
|
77
|
+
await handleGenerateStarter(genRestArgs);
|
|
78
|
+
} else {
|
|
79
|
+
console.error('Error: Invalid subcommand. Use: blok0 generate starter [folder]');
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case 'login':
|
|
85
|
+
// Check for flags
|
|
86
|
+
const tokenIndex = restArgs.indexOf('--token');
|
|
87
|
+
const manualIndex = restArgs.indexOf('--manual');
|
|
88
|
+
|
|
89
|
+
if (tokenIndex !== -1 && tokenIndex + 1 < restArgs.length) {
|
|
90
|
+
const token = restArgs[tokenIndex + 1];
|
|
91
|
+
await handleLogin(token);
|
|
92
|
+
} else if (manualIndex !== -1) {
|
|
93
|
+
await handleLogin(undefined, true);
|
|
94
|
+
} else {
|
|
95
|
+
await handleLogin();
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
|
|
99
|
+
case 'logout':
|
|
100
|
+
await handleLogout();
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case 'debug':
|
|
104
|
+
await handleDebug();
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case 'add':
|
|
108
|
+
const [addSubcommand, ...addRestArgs] = restArgs;
|
|
109
|
+
if (addSubcommand === 'block') {
|
|
110
|
+
const blockUrl = addRestArgs[0];
|
|
111
|
+
if (!blockUrl) {
|
|
112
|
+
console.error('Error: Block URL is required. Use: blok0 add block <url>');
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
const options = {
|
|
116
|
+
force: addRestArgs.includes('--force'),
|
|
117
|
+
dryRun: addRestArgs.includes('--dry-run')
|
|
118
|
+
};
|
|
119
|
+
await handleAddBlock(blockUrl, options);
|
|
120
|
+
} else {
|
|
121
|
+
console.error('Error: Invalid subcommand. Use: blok0 add block <url>');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
|
|
126
|
+
case 'update':
|
|
127
|
+
case 'remove':
|
|
128
|
+
case 'registry':
|
|
129
|
+
console.log(`${command} functionality coming soon...`);
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
default:
|
|
133
|
+
console.error(`Error: Unknown command '${command}'`);
|
|
134
|
+
showHelp();
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(`Error: ${(error as Error).message}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function handleGenerateStarter(args: string[]) {
|
|
144
|
+
let targetFolder = args[0];
|
|
145
|
+
if (!targetFolder) {
|
|
146
|
+
targetFolder = await prompt('Enter project folder name: ');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (targetFolder !== '.') {
|
|
150
|
+
mkdirSync(targetFolder, { recursive: true });
|
|
151
|
+
process.chdir(targetFolder);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!checkEmptyDirectory()) {
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
await generateStarter();
|
|
159
|
+
|
|
160
|
+
// Initialize empty registry for the new project
|
|
161
|
+
try {
|
|
162
|
+
createEmptyRegistry();
|
|
163
|
+
console.log('๐ Initialized blok0-registry.json');
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.warn('โ ๏ธ Failed to initialize registry:', (error as Error).message);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function handleDebug() {
|
|
170
|
+
console.log('๐ Blok0 CLI Debug Information');
|
|
171
|
+
console.log('==============================');
|
|
172
|
+
console.log('');
|
|
173
|
+
|
|
174
|
+
// Check stored token
|
|
175
|
+
const { getAccessToken, isAuthenticated } = await import('./auth');
|
|
176
|
+
const token = await getAccessToken();
|
|
177
|
+
const isAuth = await isAuthenticated();
|
|
178
|
+
|
|
179
|
+
console.log('๐ Authentication Status:');
|
|
180
|
+
console.log(` Authenticated: ${isAuth ? 'โ
Yes' : 'โ No'}`);
|
|
181
|
+
console.log(` Token Stored: ${token ? 'โ
Yes' : 'โ No'}`);
|
|
182
|
+
|
|
183
|
+
if (token) {
|
|
184
|
+
console.log(` Token Preview: ${token.substring(0, 20)}...`);
|
|
185
|
+
console.log(` Authorization Header: Bearer ${token}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log('');
|
|
189
|
+
console.log('๐ API Configuration:');
|
|
190
|
+
console.log(' Base URL: https://www.blok0.xyz');
|
|
191
|
+
console.log(' User Agent: blok0-cli/1.0.0');
|
|
192
|
+
|
|
193
|
+
console.log('');
|
|
194
|
+
console.log('๐งช Test API Connection:');
|
|
195
|
+
|
|
196
|
+
// Test API connection
|
|
197
|
+
const { apiClient } = await import('./api');
|
|
198
|
+
try {
|
|
199
|
+
const connectionTest = await apiClient.testConnection();
|
|
200
|
+
console.log(` Connection Test: ${connectionTest ? 'โ
Passed' : 'โ Failed'}`);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.log(` Connection Test: โ Failed - ${(error as Error).message}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
console.log('');
|
|
206
|
+
console.log('๐ก Next Steps:');
|
|
207
|
+
console.log(' 1. If no token, run: blok0 login');
|
|
208
|
+
console.log(' 2. Test API with: blok0 add block <url>');
|
|
209
|
+
console.log(' 3. Check server logs for detailed request info');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main();
|