@blu1606/create-walrus-app 1.0.0 → 2.0.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 +2 -15
- package/dist/post-install/messages.js +1 -1
- 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/{templates/gallery → presets/react-mysten-gallery}/README.md +25 -22
- package/presets/react-mysten-gallery/package.json +34 -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/index.html +13 -0
- package/{templates/react → presets/react-mysten-simple-upload}/package.json +13 -11
- 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/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/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
- /package/{templates/simple-upload → presets/react-mysten-simple-upload}/README.md +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,12 @@
|
|
|
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';
|
|
6
5
|
export async function runPostInstall(options) {
|
|
7
|
-
const { context, projectPath, skipInstall = false,
|
|
6
|
+
const { context, projectPath, skipInstall = false, skipValidation = false, } = options;
|
|
8
7
|
const result = {
|
|
9
8
|
success: true,
|
|
10
9
|
installed: false,
|
|
11
|
-
gitInitialized: false,
|
|
12
10
|
validated: false,
|
|
13
11
|
};
|
|
14
12
|
try {
|
|
@@ -23,18 +21,7 @@ export async function runPostInstall(options) {
|
|
|
23
21
|
logger.info(` ${context.packageManager} install`);
|
|
24
22
|
}
|
|
25
23
|
}
|
|
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
|
|
24
|
+
// Step 2: Validate project
|
|
38
25
|
if (!skipValidation && result.installed) {
|
|
39
26
|
const validationResult = await validateProject(projectPath);
|
|
40
27
|
result.validated = validationResult.valid;
|
|
@@ -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');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blu1606/create-walrus-app",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.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
|
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gallery-demo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This is a File Gallery Walrus application.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Upload multiple files
|
|
8
|
-
- Grid view of all files
|
|
9
|
-
-
|
|
7
|
+
- Upload multiple files to Walrus
|
|
8
|
+
- Grid view of all uploaded files
|
|
9
|
+
- Persistent index (localStorage)
|
|
10
10
|
- Delete files from gallery
|
|
11
|
-
- File metadata display
|
|
11
|
+
- File metadata display (name, size, upload date)
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
1. Click "Choose File" and select a file
|
|
16
|
+
2. Click "Add to Gallery" to upload
|
|
17
|
+
3. Files appear in the grid below
|
|
18
|
+
4. Click "Delete" to remove files from gallery
|
|
19
|
+
5. Gallery index persists in localStorage
|
|
20
|
+
|
|
21
|
+
## Code Structure
|
|
22
|
+
|
|
23
|
+
- `GalleryGrid.tsx` - Grid layout for files
|
|
24
|
+
- `FileCard.tsx` - Individual file display
|
|
25
|
+
- `UploadModal.tsx` - Upload UI
|
|
26
|
+
- `index-manager.ts` - localStorage persistence
|
|
27
|
+
- `App.tsx` - Main app layout
|
|
28
|
+
|
|
29
|
+
## Gallery Index Format
|
|
30
|
+
|
|
31
|
+
The gallery maintains a local index in localStorage:
|
|
14
32
|
|
|
15
33
|
```json
|
|
16
34
|
{
|
|
@@ -27,18 +45,3 @@ Manage multiple files with a persistent index.
|
|
|
27
45
|
"lastModified": 1705449600000
|
|
28
46
|
}
|
|
29
47
|
```
|
|
30
|
-
|
|
31
|
-
## Usage
|
|
32
|
-
|
|
33
|
-
1. Click "Choose File" to select a file
|
|
34
|
-
2. Click "Add to Gallery" to upload
|
|
35
|
-
3. Files appear in the grid below
|
|
36
|
-
4. Click "Delete" to remove files from gallery
|
|
37
|
-
|
|
38
|
-
## Code Structure
|
|
39
|
-
|
|
40
|
-
- `GalleryGrid.tsx` - Grid layout for files
|
|
41
|
-
- `FileCard.tsx` - Individual file display
|
|
42
|
-
- `UploadModal.tsx` - Upload UI
|
|
43
|
-
- `index-manager.ts` - localStorage persistence
|
|
44
|
-
- `gallery.ts` - Type definitions
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gallery-demo",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Walrus application scaffolded with create-walrus-app",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
11
|
+
"preview": "vite preview",
|
|
12
|
+
"type-check": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@mysten/dapp-kit": "^0.14.0",
|
|
16
|
+
"@mysten/sui": "^1.10.0",
|
|
17
|
+
"@mysten/walrus": "^0.9.0",
|
|
18
|
+
"@tanstack/react-query": "^5.17.0",
|
|
19
|
+
"react": "^18.2.0",
|
|
20
|
+
"react-dom": "^18.2.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/react": "^18.2.48",
|
|
24
|
+
"@types/react-dom": "^18.2.18",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
26
|
+
"@typescript-eslint/parser": "^6.19.0",
|
|
27
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
28
|
+
"eslint": "^8.56.0",
|
|
29
|
+
"eslint-plugin-react": "^7.33.2",
|
|
30
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
31
|
+
"typescript": "^5.3.3",
|
|
32
|
+
"vite": "^5.0.11"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { AppLayout } from './components/layout/app-layout.js';
|
|
3
|
+
import { GalleryGrid } from './components/features/gallery-grid.js';
|
|
4
|
+
import { UploadModal } from './components/features/upload-modal.js';
|
|
5
|
+
import './index.css';
|
|
6
|
+
|
|
7
|
+
function App() {
|
|
8
|
+
const [refreshKey, setRefreshKey] = useState(0);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<AppLayout>
|
|
12
|
+
<div className="gallery-app">
|
|
13
|
+
<h2><span className="text-accent">🖼️</span> File Gallery</h2>
|
|
14
|
+
<p className="text-secondary">Upload and manage multiple files on <span className="text-accent">Walrus</span></p>
|
|
15
|
+
|
|
16
|
+
<UploadModal onSuccess={() => setRefreshKey((k) => k + 1)} />
|
|
17
|
+
<GalleryGrid key={refreshKey} />
|
|
18
|
+
</div>
|
|
19
|
+
</AppLayout>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default App;
|