Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,19 @@ Interactive prompts guide you through:
- Template choice (when Script API is enabled)
- Package manager (npm, pnpm, yarn)

Use `--yes` to skip prompts and create with defaults (explosive-bow + BP + RP + TS):
Use `--yes` to skip all prompts and create with defaults:

```bash
mcbe-create init my-addon --yes
```

Use short flags to customize non-interactively:

```bash
mcbe-create init my-addon -a "Author" -d "My addon" -l js --no-scripts -k bp -y
mcbe-create init my-addon -v 1.20.0 -p pnpm --no-install
```

Run `init` inside an existing project to add missing packs.

### Development
Expand Down Expand Up @@ -70,7 +77,17 @@ mcbe-create info # Show project information
|-------------------|------|---------|-------------|
| `[project-name]` | `string` | — | Project name (prompted if omitted) |
| `-t, --template <template>` | `string` | `'default'` | Template to use (`default`, `explosive-bow`) |
| `-y, --yes` | `boolean` | `false` | Skip prompts, use defaults |
| `-y, --yes` | `boolean` | `false` | Skip all prompts, use defaults for unspecified fields |
| `-a, --author <author>` | `string` | `''` | Author name |
| `-d, --desc <desc>` | `string` | `''` | Project description |
| `-l, --lang <lang>` | `string` | `'typescript'` | Script language (`typescript`, `javascript`) |
| `-v, --mc-version <version>` | `string` | `'1.18.0'` | `@minecraft/server` version |
| `-p, --pm <pm>` | `string` | auto-detected | Package manager (`npm`, `pnpm`, `yarn`) |
| `-k, --packs <packs>` | `string` | `'bp,rp'` | Packs to include (`bp`, `rp`, comma-separated) |
| `--no-scripts` | `boolean` | — | Disable Minecraft Script API |
| `--no-install` | `boolean` | — | Skip dependency installation |
| `--add-bp` | `boolean` | — | Add behavior pack to existing project |
| `--add-rp` | `boolean` | — | Add resource pack to existing project |

### `dev`

Expand Down
159 changes: 159 additions & 0 deletions src/commands/__tests__/init.integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import process from 'node:process'
import { describe, expect, it } from 'vitest'
import { initCommand } from '../init.js'

function readJson(file: string) {
return JSON.parse(readFileSync(file, 'utf-8'))
}

function createTempDir() {
return mkdtempSync(join(tmpdir(), 'mcbe-test-'))
}

describe('init command integration', () => {
it('should create a project with default packs and scripts', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('test-addon', { yes: true, install: false })

expect(existsSync(join(tmp, 'test-addon', 'package.json'))).toBe(true)
expect(existsSync(join(tmp, 'test-addon', 'tsconfig.json'))).toBe(true)
expect(existsSync(join(tmp, 'test-addon', 'src', 'behavior_pack', 'manifest.json'))).toBe(true)
expect(existsSync(join(tmp, 'test-addon', 'src', 'resource_pack', 'manifest.json'))).toBe(true)

const pkg = readJson(join(tmp, 'test-addon', 'package.json'))
expect(pkg.name).toBe('test-addon')
expect(pkg.mcbe.uuids.behaviorPack).toBeTruthy()
expect(pkg.mcbe.uuids.resourcePack).toBeTruthy()
expect(pkg.mcbe.uuids.module).toBeTruthy()
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should respect --no-scripts and -k bp', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('no-scripts-test', { yes: true, install: false, scripts: false, packs: 'bp' })

expect(existsSync(join(tmp, 'no-scripts-test', 'tsconfig.json'))).toBe(false)
expect(existsSync(join(tmp, 'no-scripts-test', 'src', 'behavior_pack', 'manifest.json'))).toBe(true)
expect(existsSync(join(tmp, 'no-scripts-test', 'src', 'resource_pack', 'manifest.json'))).toBe(false)

const pkg = readJson(join(tmp, 'no-scripts-test', 'package.json'))
expect(pkg.mcbe.uuids.behaviorPack).toBeTruthy()
expect(pkg.mcbe.uuids.module).toBeFalsy()
expect(pkg.mcbe.uuids.resourcePack).toBeFalsy()
expect(pkg.dependencies).toEqual({})
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should respect -l js', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('js-test', { yes: true, install: false, lang: 'javascript' })

expect(existsSync(join(tmp, 'js-test', 'tsconfig.json'))).toBe(false)
expect(existsSync(join(tmp, 'js-test', 'src', 'behavior_pack', 'scripts', 'main.js'))).toBe(true)
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should respect -a and -d', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('author-test', { yes: true, install: false, author: 'Test Author', desc: 'Test Description' })

const pkg = readJson(join(tmp, 'author-test', 'package.json'))
expect(pkg.author).toBe('Test Author')
expect(pkg.description).toBe('Test Description')
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should respect -v for mc-version', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('version-test', { yes: true, install: false, mcVersion: '1.20.0' })

const pkg = readJson(join(tmp, 'version-test', 'package.json'))
expect(pkg.dependencies['@minecraft/server']).toBe('1.20.0')
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should respect -p pm override', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('pm-test', { yes: true, install: false, pm: 'npm' })

const pkg = readJson(join(tmp, 'pm-test', 'package.json'))
expect(existsSync(join(tmp, 'pm-test', 'pnpm-lock.yaml'))).toBe(false)
expect(pkg.name).toBe('pm-test')
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})

it('should support full non-interactive creation with all flags', async () => {
const tmp = createTempDir()
const cwd = process.cwd()
process.chdir(tmp)
try {
await initCommand('full-flags', {
yes: true,
install: false,
author: 'Dev',
desc: 'Full test',
lang: 'typescript',
mcVersion: '1.21.0',
pm: 'pnpm',
packs: 'bp,rp',
template: 'default',
})
expect(existsSync(join(tmp, 'full-flags', 'src', 'behavior_pack', 'manifest.json'))).toBe(true)
expect(existsSync(join(tmp, 'full-flags', 'src', 'resource_pack', 'manifest.json'))).toBe(true)

const pkg = readJson(join(tmp, 'full-flags', 'package.json'))
expect(pkg.author).toBe('Dev')
expect(pkg.description).toBe('Full test')
expect(pkg.dependencies['@minecraft/server']).toBe('1.21.0')
}
finally {
process.chdir(cwd)
rmSync(tmp, { recursive: true })
}
})
})
34 changes: 34 additions & 0 deletions src/commands/__tests__/init.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from 'vitest'
import { parsePacks } from '../init.js'

describe('parsePacks', () => {
it('should default to both packs when no argument given', () => {
expect(parsePacks()).toEqual(['behavior_pack', 'resource_pack'])
expect(parsePacks(undefined)).toEqual(['behavior_pack', 'resource_pack'])
})

it('should parse "bp" as behavior_pack', () => {
expect(parsePacks('bp')).toEqual(['behavior_pack'])
})

it('should parse "rp" as resource_pack', () => {
expect(parsePacks('rp')).toEqual(['resource_pack'])
})

it('should parse comma-separated packs', () => {
expect(parsePacks('bp,rp')).toEqual(['behavior_pack', 'resource_pack'])
})

it('should parse full names', () => {
expect(parsePacks('behavior_pack,resource_pack')).toEqual(['behavior_pack', 'resource_pack'])
expect(parsePacks('behavior_pack')).toEqual(['behavior_pack'])
})

it('should trim whitespace', () => {
expect(parsePacks(' bp , rp ')).toEqual(['behavior_pack', 'resource_pack'])
})

it('should pass through unknown values', () => {
expect(parsePacks('bp,custom_pack')).toEqual(['behavior_pack', 'custom_pack'] as any)
})
})
Loading
Loading