@blu1606/create-walrus-app 1.0.0 → 2.1.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/generator/file-ops.d.ts +8 -0
- package/dist/generator/file-ops.js +20 -0
- package/dist/generator/index.js +37 -22
- package/dist/generator/layers.d.ts +15 -2
- package/dist/generator/layers.js +38 -47
- package/dist/generator/types.d.ts +9 -1
- package/dist/index.js +1 -2
- package/dist/post-install/git.d.ts +8 -0
- package/dist/post-install/git.js +2 -0
- package/dist/post-install/index.d.ts +0 -1
- package/dist/post-install/index.js +7 -15
- package/dist/post-install/messages.js +1 -1
- package/dist/post-install/walrus-deploy.d.ts +6 -0
- package/dist/post-install/walrus-deploy.js +77 -0
- package/package.json +3 -3
- package/{templates/base → presets/react-mysten-gallery}/.env.example +31 -31
- package/presets/react-mysten-gallery/.gitkeep +4 -0
- package/presets/react-mysten-gallery/README.md +107 -0
- package/presets/react-mysten-gallery/package.json +35 -0
- package/presets/react-mysten-gallery/scripts/setup-walrus-deploy.sh +286 -0
- package/presets/react-mysten-gallery/src/App.tsx +23 -0
- package/presets/react-mysten-gallery/src/components/features/file-card.tsx +89 -0
- package/{templates/gallery/src/components/GalleryGrid.tsx → presets/react-mysten-gallery/src/components/features/gallery-grid.tsx} +5 -5
- package/presets/react-mysten-gallery/src/components/features/upload-modal.tsx +69 -0
- package/{templates/react/src/components/WalletConnect.tsx → presets/react-mysten-gallery/src/components/features/wallet-connect.tsx} +1 -1
- package/presets/react-mysten-gallery/src/components/layout/app-layout.tsx +21 -0
- package/{templates/react/src/hooks/useStorage.ts → presets/react-mysten-gallery/src/hooks/use-download.ts} +2 -18
- package/presets/react-mysten-gallery/src/hooks/use-upload.ts +49 -0
- package/{templates/react/src/hooks/useWallet.ts → presets/react-mysten-gallery/src/hooks/use-wallet.ts} +2 -7
- package/presets/react-mysten-gallery/src/index.css +384 -0
- package/presets/react-mysten-gallery/src/index.ts +17 -0
- package/presets/react-mysten-gallery/src/lib/walrus/adapter.ts +197 -0
- package/presets/react-mysten-gallery/src/lib/walrus/client.ts +87 -0
- package/presets/react-mysten-gallery/src/lib/walrus/index.ts +4 -0
- package/presets/react-mysten-gallery/src/lib/walrus/types.ts +101 -0
- package/{templates/react → presets/react-mysten-gallery}/src/main.tsx +0 -1
- package/{templates/react → presets/react-mysten-gallery}/src/providers/WalletProvider.tsx +16 -1
- package/{templates/base → presets/react-mysten-gallery}/src/utils/env.ts +41 -41
- package/{templates/gallery → presets/react-mysten-gallery}/src/utils/index-manager.ts +2 -2
- package/presets/react-mysten-gallery/src/utils/mime-type.ts +97 -0
- package/presets/react-mysten-gallery/src/utils/preview-generator.ts +134 -0
- package/{templates/react → presets/react-mysten-gallery}/tsconfig.json +20 -8
- package/presets/react-mysten-simple-upload/.env.example +31 -0
- package/presets/react-mysten-simple-upload/.gitkeep +4 -0
- package/presets/react-mysten-simple-upload/README.md +84 -0
- package/presets/react-mysten-simple-upload/index.html +13 -0
- package/{templates/react → presets/react-mysten-simple-upload}/package.json +15 -12
- package/presets/react-mysten-simple-upload/scripts/setup-walrus-deploy.sh +286 -0
- package/presets/react-mysten-simple-upload/src/App.tsx +27 -0
- package/presets/react-mysten-simple-upload/src/components/features/file-preview.tsx +73 -0
- package/{templates/simple-upload/src/components/UploadForm.tsx → presets/react-mysten-simple-upload/src/components/features/upload-form.tsx} +15 -5
- package/presets/react-mysten-simple-upload/src/components/features/wallet-connect.tsx +21 -0
- package/presets/react-mysten-simple-upload/src/components/layout/app-layout.tsx +21 -0
- package/presets/react-mysten-simple-upload/src/hooks/use-download.ts +24 -0
- package/presets/react-mysten-simple-upload/src/hooks/use-upload.ts +49 -0
- package/presets/react-mysten-simple-upload/src/hooks/use-wallet.ts +11 -0
- package/presets/react-mysten-simple-upload/src/index.css +252 -0
- package/presets/react-mysten-simple-upload/src/index.ts +16 -0
- package/presets/react-mysten-simple-upload/src/lib/walrus/adapter.ts +197 -0
- package/presets/react-mysten-simple-upload/src/lib/walrus/client.ts +87 -0
- package/presets/react-mysten-simple-upload/src/lib/walrus/index.ts +4 -0
- package/{templates/base/src/adapters/storage.ts → presets/react-mysten-simple-upload/src/lib/walrus/types.ts} +83 -58
- package/presets/react-mysten-simple-upload/src/main.tsx +16 -0
- package/presets/react-mysten-simple-upload/src/providers/QueryProvider.tsx +18 -0
- package/presets/react-mysten-simple-upload/src/providers/WalletProvider.tsx +52 -0
- package/presets/react-mysten-simple-upload/src/utils/env.ts +41 -0
- package/presets/react-mysten-simple-upload/src/utils/mime-type.ts +97 -0
- package/presets/react-mysten-simple-upload/tsconfig.json +39 -0
- package/presets/react-mysten-simple-upload/tsconfig.node.json +10 -0
- package/presets/react-mysten-simple-upload/vite.config.ts +19 -0
- package/templates/base/README.md +0 -54
- package/templates/base/package.json +0 -19
- package/templates/base/src/types/index.ts +0 -9
- package/templates/base/src/types/walrus.ts +0 -22
- package/templates/base/src/utils/format.ts +0 -29
- package/templates/base/tsconfig.json +0 -19
- package/templates/gallery/README.md +0 -44
- package/templates/gallery/package.json +0 -6
- package/templates/gallery/src/App.tsx +0 -21
- package/templates/gallery/src/components/FileCard.tsx +0 -27
- package/templates/gallery/src/components/UploadModal.tsx +0 -45
- package/templates/gallery/src/styles.css +0 -58
- package/templates/gallery/src/types/gallery.ts +0 -13
- package/templates/react/.eslintrc.json +0 -26
- package/templates/react/README.md +0 -80
- package/templates/react/src/App.tsx +0 -14
- package/templates/react/src/components/Layout.tsx +0 -21
- package/templates/react/src/dapp-kit.css +0 -1
- package/templates/react/src/index.css +0 -50
- package/templates/react/src/index.ts +0 -10
- package/templates/sdk-mysten/README.md +0 -65
- package/templates/sdk-mysten/package.json +0 -14
- package/templates/sdk-mysten/src/adapter.ts +0 -80
- package/templates/sdk-mysten/src/client.ts +0 -45
- package/templates/sdk-mysten/src/config.ts +0 -33
- package/templates/sdk-mysten/src/index.ts +0 -11
- package/templates/sdk-mysten/src/types.ts +0 -19
- package/templates/sdk-mysten/test/adapter.test.ts +0 -20
- package/templates/simple-upload/README.md +0 -24
- package/templates/simple-upload/package.json +0 -6
- package/templates/simple-upload/src/App.tsx +0 -27
- package/templates/simple-upload/src/components/FilePreview.tsx +0 -40
- package/templates/simple-upload/src/styles.css +0 -33
- /package/{templates/react → presets/react-mysten-gallery}/index.html +0 -0
- /package/{templates/react → presets/react-mysten-gallery}/src/providers/QueryProvider.tsx +0 -0
- /package/{templates/react → presets/react-mysten-gallery}/tsconfig.node.json +0 -0
- /package/{templates/react → presets/react-mysten-gallery}/vite.config.ts +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export interface EnvCopyResult {
|
|
2
|
+
created: boolean;
|
|
3
|
+
reason?: 'no-source' | 'already-exists';
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* Recursively copy directory, excluding certain files
|
|
3
7
|
*/
|
|
@@ -10,3 +14,7 @@ export declare function isDirectoryEmpty(dir: string): Promise<boolean>;
|
|
|
10
14
|
* Create directory if it doesn't exist
|
|
11
15
|
*/
|
|
12
16
|
export declare function ensureDirectory(dir: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Copy .env.example to .env if it doesn't exist
|
|
19
|
+
*/
|
|
20
|
+
export declare function copyEnvFile(targetDir: string): Promise<EnvCopyResult>;
|
|
@@ -38,3 +38,23 @@ export async function isDirectoryEmpty(dir) {
|
|
|
38
38
|
export async function ensureDirectory(dir) {
|
|
39
39
|
await fs.ensureDir(dir);
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Copy .env.example to .env if it doesn't exist
|
|
43
|
+
*/
|
|
44
|
+
export async function copyEnvFile(targetDir) {
|
|
45
|
+
const envExamplePath = path.join(targetDir, '.env.example');
|
|
46
|
+
const envPath = path.join(targetDir, '.env');
|
|
47
|
+
// Check if .env.example exists
|
|
48
|
+
const hasExample = await fs.pathExists(envExamplePath);
|
|
49
|
+
if (!hasExample) {
|
|
50
|
+
return { created: false, reason: 'no-source' };
|
|
51
|
+
}
|
|
52
|
+
// Check if .env already exists
|
|
53
|
+
const hasEnv = await fs.pathExists(envPath);
|
|
54
|
+
if (hasEnv) {
|
|
55
|
+
return { created: false, reason: 'already-exists' };
|
|
56
|
+
}
|
|
57
|
+
// Copy file
|
|
58
|
+
await fs.copy(envExamplePath, envPath);
|
|
59
|
+
return { created: true };
|
|
60
|
+
}
|
package/dist/generator/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fs from 'fs-extra';
|
|
3
2
|
import { logger } from '../utils/logger.js';
|
|
4
|
-
import {
|
|
5
|
-
import { copyDirectory, ensureDirectory, isDirectoryEmpty, } from './file-ops.js';
|
|
6
|
-
import { mergePackageJsonFiles } from './merge.js';
|
|
3
|
+
import { resolvePresetPath, getPresetName } from './layers.js';
|
|
4
|
+
import { copyDirectory, ensureDirectory, isDirectoryEmpty, copyEnvFile, } from './file-ops.js';
|
|
7
5
|
import { buildVariables, transformDirectory } from './transform.js';
|
|
8
6
|
export async function generateProject(options) {
|
|
9
7
|
const { context, targetDir, dryRun = false } = options;
|
|
@@ -17,26 +15,21 @@ export async function generateProject(options) {
|
|
|
17
15
|
}
|
|
18
16
|
await ensureDirectory(targetDir);
|
|
19
17
|
}
|
|
20
|
-
// Resolve
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
logger.info(`📁 Copying layer: ${layer.name}`);
|
|
31
|
-
if (!dryRun) {
|
|
32
|
-
const count = await copyDirectory(layer.path, targetDir);
|
|
33
|
-
filesCreated += count;
|
|
34
|
-
}
|
|
18
|
+
// Resolve preset path
|
|
19
|
+
const presetName = getPresetName(context);
|
|
20
|
+
const presetPath = resolvePresetPath(context);
|
|
21
|
+
logger.info(`📦 Using preset: ${presetName}`);
|
|
22
|
+
// Validate preset exists
|
|
23
|
+
if (!(await fs.pathExists(presetPath))) {
|
|
24
|
+
throw new Error(`Preset not found: ${presetName}\n` +
|
|
25
|
+
`Expected at: ${presetPath}\n` +
|
|
26
|
+
`Available presets: Check packages/cli/presets/`);
|
|
35
27
|
}
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
let filesCreated = 0;
|
|
29
|
+
// Copy preset directory to target
|
|
30
|
+
logger.info(`📁 Copying preset files...`);
|
|
38
31
|
if (!dryRun) {
|
|
39
|
-
await
|
|
32
|
+
filesCreated = await copyDirectory(presetPath, targetDir);
|
|
40
33
|
}
|
|
41
34
|
// Transform template variables
|
|
42
35
|
logger.info('✏️ Transforming template variables');
|
|
@@ -44,8 +37,30 @@ export async function generateProject(options) {
|
|
|
44
37
|
const vars = buildVariables(context);
|
|
45
38
|
await transformDirectory(targetDir, vars);
|
|
46
39
|
}
|
|
40
|
+
// Copy .env.example to .env
|
|
41
|
+
logger.info('🔐 Setting up environment file');
|
|
42
|
+
if (!dryRun) {
|
|
43
|
+
try {
|
|
44
|
+
const envResult = await copyEnvFile(targetDir);
|
|
45
|
+
if (envResult.created) {
|
|
46
|
+
logger.success('✓ Created .env from .env.example');
|
|
47
|
+
}
|
|
48
|
+
else if (envResult.reason === 'already-exists') {
|
|
49
|
+
logger.info('ℹ️ .env already exists, skipped');
|
|
50
|
+
}
|
|
51
|
+
// Silent if no-source (not all presets have .env.example)
|
|
52
|
+
}
|
|
53
|
+
catch (envError) {
|
|
54
|
+
// Non-critical: continue generation even if env copy fails
|
|
55
|
+
logger.warn(`⚠️ Could not copy .env file: ${envError}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
logger.info('(dry-run) Would copy .env.example to .env');
|
|
60
|
+
}
|
|
47
61
|
logger.success(`✓ Project generated successfully!`);
|
|
48
62
|
logger.info(`📂 Files created: ${filesCreated}`);
|
|
63
|
+
logger.info(`📦 Preset used: ${presetName}`);
|
|
49
64
|
return {
|
|
50
65
|
success: true,
|
|
51
66
|
projectPath: targetDir,
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { Context } from '../types.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Generate preset name from context
|
|
4
|
+
* Format: {framework}-{sdk}-{useCase}[-optional-features]
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* - react-mysten-simple-upload
|
|
8
|
+
* - react-mysten-gallery-enoki
|
|
9
|
+
* - vue-mysten-gallery-tailwind
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPresetName(context: Context): string;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve preset path from context
|
|
14
|
+
* Returns the absolute path to the preset directory
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolvePresetPath(context: Context): string;
|
package/dist/generator/layers.js
CHANGED
|
@@ -2,58 +2,49 @@ import path from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
const __filename = fileURLToPath(import.meta.url);
|
|
4
4
|
const __dirname = path.dirname(__filename);
|
|
5
|
-
//
|
|
6
|
-
const
|
|
5
|
+
// Presets are in packages/cli/presets (published with package)
|
|
6
|
+
const PRESETS_ROOT = path.join(__dirname, '../../presets');
|
|
7
7
|
/**
|
|
8
|
-
* Validate that a
|
|
8
|
+
* Validate that a preset path is within the presets root (prevent path traversal)
|
|
9
9
|
*/
|
|
10
|
-
function
|
|
11
|
-
const normalized = path.resolve(
|
|
12
|
-
const root = path.resolve(
|
|
10
|
+
function validatePresetPath(presetPath) {
|
|
11
|
+
const normalized = path.resolve(presetPath);
|
|
12
|
+
const root = path.resolve(PRESETS_ROOT);
|
|
13
13
|
if (!normalized.startsWith(root)) {
|
|
14
|
-
throw new Error(`Invalid
|
|
14
|
+
throw new Error(`Invalid preset path: ${presetPath} is outside presets root`);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
name: context.framework,
|
|
31
|
-
path: path.join(TEMPLATE_ROOT, context.framework),
|
|
32
|
-
priority: 3,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: context.useCase,
|
|
36
|
-
path: path.join(TEMPLATE_ROOT, context.useCase),
|
|
37
|
-
priority: 4,
|
|
38
|
-
},
|
|
39
|
-
];
|
|
40
|
-
// Optional: Tailwind layer
|
|
41
|
-
if (context.tailwind) {
|
|
42
|
-
layers.push({
|
|
43
|
-
name: 'tailwind',
|
|
44
|
-
path: path.join(TEMPLATE_ROOT, 'tailwind'),
|
|
45
|
-
priority: 5,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
// Optional: Analytics layer
|
|
17
|
+
/**
|
|
18
|
+
* Generate preset name from context
|
|
19
|
+
* Format: {framework}-{sdk}-{useCase}[-optional-features]
|
|
20
|
+
*
|
|
21
|
+
* Examples:
|
|
22
|
+
* - react-mysten-simple-upload
|
|
23
|
+
* - react-mysten-gallery-enoki
|
|
24
|
+
* - vue-mysten-gallery-tailwind
|
|
25
|
+
*/
|
|
26
|
+
export function getPresetName(context) {
|
|
27
|
+
const parts = [context.framework, context.sdk, context.useCase];
|
|
28
|
+
// Add optional features in alphabetical order
|
|
29
|
+
const optionalFeatures = [];
|
|
49
30
|
if (context.analytics) {
|
|
50
|
-
|
|
51
|
-
name: 'analytics',
|
|
52
|
-
path: path.join(TEMPLATE_ROOT, 'analytics'),
|
|
53
|
-
priority: 6,
|
|
54
|
-
});
|
|
31
|
+
optionalFeatures.push('analytics');
|
|
55
32
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
33
|
+
if (context.tailwind) {
|
|
34
|
+
optionalFeatures.push('tailwind');
|
|
35
|
+
}
|
|
36
|
+
// Sort for consistency
|
|
37
|
+
optionalFeatures.sort();
|
|
38
|
+
return [...parts, ...optionalFeatures].join('-');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve preset path from context
|
|
42
|
+
* Returns the absolute path to the preset directory
|
|
43
|
+
*/
|
|
44
|
+
export function resolvePresetPath(context) {
|
|
45
|
+
const presetName = getPresetName(context);
|
|
46
|
+
const presetPath = path.join(PRESETS_ROOT, presetName);
|
|
47
|
+
// Validate path for security
|
|
48
|
+
validatePresetPath(presetPath);
|
|
49
|
+
return presetPath;
|
|
59
50
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { Context } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated Layer-based architecture replaced with presets
|
|
4
|
+
* This interface is kept for backward compatibility but no longer used
|
|
5
|
+
*/
|
|
2
6
|
export interface Layer {
|
|
3
7
|
name: string;
|
|
4
8
|
path: string;
|
|
@@ -6,7 +10,11 @@ export interface Layer {
|
|
|
6
10
|
}
|
|
7
11
|
export interface GeneratorOptions {
|
|
8
12
|
context: Context;
|
|
9
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated templateDir no longer used (presets are resolved automatically)
|
|
15
|
+
* Kept for backward compatibility
|
|
16
|
+
*/
|
|
17
|
+
templateDir?: string;
|
|
10
18
|
targetDir: string;
|
|
11
19
|
dryRun?: boolean;
|
|
12
20
|
}
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ program
|
|
|
27
27
|
// .option('--analytics', 'Include Blockberry analytics', false)
|
|
28
28
|
// .option('--no-tailwind', 'Exclude Tailwind CSS')
|
|
29
29
|
.option('--skip-install', 'Skip dependency installation', false)
|
|
30
|
-
.option('--skip-git', '
|
|
30
|
+
.option('--skip-git', '[DEPRECATED] No longer used - git initialization removed', false)
|
|
31
31
|
.option('--skip-validation', 'Skip project validation', false)
|
|
32
32
|
.option('-p, --package-manager <pm>', 'Package manager to use (npm | pnpm | yarn | bun)')
|
|
33
33
|
.action(async (projectNameArg, options) => {
|
|
@@ -59,7 +59,6 @@ program
|
|
|
59
59
|
logger.info('\n🏗️ Generating your Walrus application...\n');
|
|
60
60
|
const result = await generateProject({
|
|
61
61
|
context,
|
|
62
|
-
templateDir: join(__dirname, '../templates'),
|
|
63
62
|
targetDir: context.projectPath,
|
|
64
63
|
});
|
|
65
64
|
// Clear tracking after completion
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Git initialization has been removed from create-walrus-app.
|
|
3
|
+
* Users should manually initialize git if needed: `git init && git add . && git commit -m "Initial commit"`
|
|
4
|
+
*
|
|
5
|
+
* This file is kept for backwards compatibility but is no longer used by the CLI.
|
|
6
|
+
*/
|
|
1
7
|
export interface GitResult {
|
|
2
8
|
success: boolean;
|
|
3
9
|
error?: Error;
|
|
4
10
|
}
|
|
5
11
|
/**
|
|
6
12
|
* Initialize git repository
|
|
13
|
+
* @deprecated Git initialization has been removed from create-walrus-app post-install flow.
|
|
7
14
|
*/
|
|
8
15
|
export declare function initializeGit(projectPath: string): Promise<GitResult>;
|
|
9
16
|
/**
|
|
10
17
|
* Create initial commit
|
|
18
|
+
* @deprecated Git initialization has been removed from create-walrus-app post-install flow.
|
|
11
19
|
*/
|
|
12
20
|
export declare function createInitialCommit(projectPath: string): Promise<GitResult>;
|
package/dist/post-install/git.js
CHANGED
|
@@ -14,6 +14,7 @@ async function isGitAvailable() {
|
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Initialize git repository
|
|
17
|
+
* @deprecated Git initialization has been removed from create-walrus-app post-install flow.
|
|
17
18
|
*/
|
|
18
19
|
export async function initializeGit(projectPath) {
|
|
19
20
|
// Check if git is available
|
|
@@ -52,6 +53,7 @@ export async function initializeGit(projectPath) {
|
|
|
52
53
|
}
|
|
53
54
|
/**
|
|
54
55
|
* Create initial commit
|
|
56
|
+
* @deprecated Git initialization has been removed from create-walrus-app post-install flow.
|
|
55
57
|
*/
|
|
56
58
|
export async function createInitialCommit(projectPath) {
|
|
57
59
|
if (!(await fs.pathExists(path.join(projectPath, '.git')))) {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { logger } from '../utils/logger.js';
|
|
2
2
|
import { installDependencies } from './package-manager.js';
|
|
3
|
-
import { initializeGit, createInitialCommit } from './git.js';
|
|
4
3
|
import { validateProject } from './validator.js';
|
|
5
4
|
import { displaySuccess, displayError } from './messages.js';
|
|
5
|
+
import { setupWalrusDeploy } from './walrus-deploy.js';
|
|
6
6
|
export async function runPostInstall(options) {
|
|
7
|
-
const { context, projectPath, skipInstall = false,
|
|
7
|
+
const { context, projectPath, skipInstall = false, skipValidation = false, } = options;
|
|
8
8
|
const result = {
|
|
9
9
|
success: true,
|
|
10
10
|
installed: false,
|
|
11
|
-
gitInitialized: false,
|
|
12
11
|
validated: false,
|
|
13
12
|
};
|
|
14
13
|
try {
|
|
@@ -23,18 +22,7 @@ export async function runPostInstall(options) {
|
|
|
23
22
|
logger.info(` ${context.packageManager} install`);
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
|
-
// Step 2:
|
|
27
|
-
if (!skipGit) {
|
|
28
|
-
const gitResult = await initializeGit(projectPath);
|
|
29
|
-
result.gitInitialized = gitResult.success;
|
|
30
|
-
if (gitResult.success) {
|
|
31
|
-
const commitResult = await createInitialCommit(projectPath);
|
|
32
|
-
if (!commitResult.success) {
|
|
33
|
-
logger.warn('⚠️ Initial commit failed, but git repo was created');
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Step 3: Validate project
|
|
25
|
+
// Step 2: Validate project
|
|
38
26
|
if (!skipValidation && result.installed) {
|
|
39
27
|
const validationResult = await validateProject(projectPath);
|
|
40
28
|
result.validated = validationResult.valid;
|
|
@@ -43,6 +31,10 @@ export async function runPostInstall(options) {
|
|
|
43
31
|
validationResult.errors.forEach((err) => logger.warn(` - ${err}`));
|
|
44
32
|
}
|
|
45
33
|
}
|
|
34
|
+
// Step 3: Setup Walrus deployment (interactive prompt)
|
|
35
|
+
if (result.installed) {
|
|
36
|
+
await setupWalrusDeploy(projectPath, context);
|
|
37
|
+
}
|
|
46
38
|
// Display success message
|
|
47
39
|
displaySuccess(context);
|
|
48
40
|
return result;
|
|
@@ -16,6 +16,7 @@ export function displaySuccess(context) {
|
|
|
16
16
|
console.log('\n' + kleur.bold('🚀 Next Steps:'));
|
|
17
17
|
console.log(` ${kleur.gray('1.')} cd ${kleur.cyan(projectName)}`);
|
|
18
18
|
console.log(` ${kleur.gray('2.')} ${kleur.cyan(getRunCommand(packageManager, 'dev'))}`);
|
|
19
|
+
console.log(` ${kleur.gray('Note:')} .env file created automatically`);
|
|
19
20
|
console.log('\n' + kleur.bold('📚 Helpful Commands:'));
|
|
20
21
|
console.log(` ${kleur.cyan(getRunCommand(packageManager, 'dev'))} - Start development server`);
|
|
21
22
|
console.log(` ${kleur.cyan(getRunCommand(packageManager, 'build'))} - Build for production`);
|
|
@@ -25,7 +26,6 @@ export function displaySuccess(context) {
|
|
|
25
26
|
console.log(` Sui Docs: ${kleur.cyan('https://docs.sui.io')}`);
|
|
26
27
|
console.log(` Sui Faucet: ${kleur.cyan('https://faucet.testnet.sui.io')}`);
|
|
27
28
|
console.log('\n' + kleur.bold('💡 Tips:'));
|
|
28
|
-
console.log(` - Copy ${kleur.cyan('.env.example')} to ${kleur.cyan('.env')}`);
|
|
29
29
|
console.log(` - Install Sui Wallet browser extension`);
|
|
30
30
|
console.log(` - Get testnet SUI from the faucet`);
|
|
31
31
|
console.log('\n' + kleur.green('━'.repeat(60)) + '\n');
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import { spawn } from 'cross-spawn';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { existsSync, chmodSync } from 'node:fs';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Prompts user to setup Walrus Sites deployment
|
|
8
|
+
* Runs setup-walrus-deploy.sh script if user confirms
|
|
9
|
+
*/
|
|
10
|
+
export async function setupWalrusDeploy(projectPath, _context) {
|
|
11
|
+
try {
|
|
12
|
+
const isInteractive = Boolean(process.stdin.isTTY);
|
|
13
|
+
// Skip in non-interactive mode
|
|
14
|
+
if (!isInteractive) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
console.log(''); // Newline for better spacing
|
|
18
|
+
const response = await prompts({
|
|
19
|
+
type: 'confirm',
|
|
20
|
+
name: 'setup',
|
|
21
|
+
message: 'Setup Walrus Sites deployment? (testnet)',
|
|
22
|
+
initial: false,
|
|
23
|
+
}, {
|
|
24
|
+
onCancel: () => {
|
|
25
|
+
logger.info('Skipping Walrus deployment setup');
|
|
26
|
+
return false;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
if (!response.setup) {
|
|
30
|
+
logger.info('You can setup later by running: pnpm setup-walrus-deploy');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Run the setup script
|
|
34
|
+
const scriptPath = join(projectPath, 'scripts', 'setup-walrus-deploy.sh');
|
|
35
|
+
if (!existsSync(scriptPath)) {
|
|
36
|
+
logger.warn('⚠️ setup-walrus-deploy.sh not found in project scripts/');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Make script executable (Unix/macOS)
|
|
40
|
+
try {
|
|
41
|
+
chmodSync(scriptPath, 0o755);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
// Ignore on Windows
|
|
45
|
+
}
|
|
46
|
+
logger.info('🦭 Running Walrus deployment setup...\n');
|
|
47
|
+
// Execute setup script
|
|
48
|
+
const child = spawn('bash', [scriptPath, projectPath], {
|
|
49
|
+
cwd: projectPath,
|
|
50
|
+
stdio: 'inherit', // Show output in real-time
|
|
51
|
+
shell: true,
|
|
52
|
+
});
|
|
53
|
+
await new Promise((resolve, reject) => {
|
|
54
|
+
child.on('close', (code) => {
|
|
55
|
+
if (code === 0) {
|
|
56
|
+
logger.success('\n✅ Walrus deployment setup complete!');
|
|
57
|
+
resolve();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger.warn(`\n⚠️ Setup exited with code ${code}. You can retry with: pnpm setup-walrus-deploy`);
|
|
61
|
+
resolve(); // Don't fail the whole installation
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
child.on('error', (error) => {
|
|
65
|
+
logger.error(`Setup script error: ${error.message}`);
|
|
66
|
+
reject(error);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// Non-fatal: log and continue
|
|
72
|
+
logger.warn('⚠️ Walrus deployment setup skipped due to error');
|
|
73
|
+
if (error instanceof Error) {
|
|
74
|
+
logger.warn(error.message);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blu1606/create-walrus-app",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Interactive CLI for scaffolding Walrus applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"
|
|
11
|
+
"presets",
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
14
|
"keywords": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "https://github.com/
|
|
25
|
+
"url": "https://github.com/Walrus-starter-kit/walrus-starter-kit.git",
|
|
26
26
|
"directory": "packages/cli"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
## ==============================================
|
|
2
|
-
## Walrus Application - Environment Configuration
|
|
3
|
-
## ==============================================
|
|
4
|
-
|
|
5
|
-
## WALRUS NETWORK SETTINGS
|
|
6
|
-
## Network: testnet | mainnet | devnet
|
|
7
|
-
VITE_WALRUS_NETWORK=testnet
|
|
8
|
-
|
|
9
|
-
## Walrus Aggregator URL (for downloads)
|
|
10
|
-
VITE_WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
|
|
11
|
-
|
|
12
|
-
## Walrus Publisher URL (for uploads)
|
|
13
|
-
VITE_WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
|
|
14
|
-
|
|
15
|
-
## SUI BLOCKCHAIN SETTINGS
|
|
16
|
-
## Sui Network: testnet | mainnet | devnet
|
|
17
|
-
VITE_SUI_NETWORK=testnet
|
|
18
|
-
|
|
19
|
-
## Sui RPC URL (for wallet interactions)
|
|
20
|
-
VITE_SUI_RPC=https://fullnode.testnet.sui.io:443
|
|
21
|
-
|
|
22
|
-
## OPTIONAL FEATURES
|
|
23
|
-
## Blockberry Analytics API Key (leave empty to disable)
|
|
24
|
-
VITE_BLOCKBERRY_KEY=
|
|
25
|
-
|
|
26
|
-
## ==============================================
|
|
27
|
-
## PREREQUISITES
|
|
28
|
-
## ==============================================
|
|
29
|
-
## 1. Install Sui Wallet browser extension
|
|
30
|
-
## 2. Get testnet SUI from faucet: https://faucet.testnet.sui.io/
|
|
31
|
-
## 3. Copy this file to .env and fill in any optional values
|
|
1
|
+
## ==============================================
|
|
2
|
+
## Walrus Application - Environment Configuration
|
|
3
|
+
## ==============================================
|
|
4
|
+
|
|
5
|
+
## WALRUS NETWORK SETTINGS
|
|
6
|
+
## Network: testnet | mainnet | devnet
|
|
7
|
+
VITE_WALRUS_NETWORK=testnet
|
|
8
|
+
|
|
9
|
+
## Walrus Aggregator URL (for downloads)
|
|
10
|
+
VITE_WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
|
|
11
|
+
|
|
12
|
+
## Walrus Publisher URL (for uploads)
|
|
13
|
+
VITE_WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
|
|
14
|
+
|
|
15
|
+
## SUI BLOCKCHAIN SETTINGS
|
|
16
|
+
## Sui Network: testnet | mainnet | devnet
|
|
17
|
+
VITE_SUI_NETWORK=testnet
|
|
18
|
+
|
|
19
|
+
## Sui RPC URL (for wallet interactions)
|
|
20
|
+
VITE_SUI_RPC=https://fullnode.testnet.sui.io:443
|
|
21
|
+
|
|
22
|
+
## OPTIONAL FEATURES
|
|
23
|
+
## Blockberry Analytics API Key (leave empty to disable)
|
|
24
|
+
VITE_BLOCKBERRY_KEY=
|
|
25
|
+
|
|
26
|
+
## ==============================================
|
|
27
|
+
## PREREQUISITES
|
|
28
|
+
## ==============================================
|
|
29
|
+
## 1. Install Sui Wallet browser extension
|
|
30
|
+
## 2. Get testnet SUI from faucet: https://faucet.testnet.sui.io/
|
|
31
|
+
## 3. Copy this file to .env and fill in any optional values
|