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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Fixed templates not being extracted when using `bunx create-ely` due to Bun's default-secure lifecycle scripts policy
- Added runtime template extraction to ensure templates are available regardless of postinstall execution

## [0.1.3] - 2026-01-04

### Added
Expand Down
44 changes: 44 additions & 0 deletions src/template.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
import { copyFileSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import * as clack from '@clack/prompts';
import AdmZip from 'adm-zip';
import {
EXCLUDED_COPY_PATTERNS,
TEMPLATE_PATHS,
TEMPLATE_TYPES,
} from './constants.ts';
import { copyRecursive } from './utils.ts';

/**
* Ensures templates are extracted from zip if not already present
* This handles cases where postinstall didn't run (e.g., bunx)
*
* Bun uses a "default-secure" approach where lifecycle scripts are not
* executed by default. When users run `bunx create-ely`, the postinstall
* script doesn't run, so we extract templates at runtime instead.
*/
function ensureTemplatesExtracted(): void {
const templatesPath = join(import.meta.dir, '..', 'templates');
const zipPath = join(import.meta.dir, '..', 'templates.zip');

// Templates already exist (source repo or already extracted)
if (existsSync(templatesPath)) {
return;
}

// Extract from zip if available
if (!existsSync(zipPath)) {
throw new Error(
'templates.zip not found. Installation may be corrupted.\n' +
'Report this issue: https://github.com/truehazker/create-ely/issues',
);
}

try {
const zip = new AdmZip(zipPath);
zip.extractAllTo(templatesPath, true);

if (!existsSync(templatesPath)) {
throw new Error('Templates folder was not created after extraction');
}
} catch (error) {
throw new Error(
`Failed to extract templates: ${error instanceof Error ? error.message : error}\n` +
'Report this issue: https://github.com/truehazker/create-ely/issues',
);
}
}

/**
* Sets up the project template by copying files and installing dependencies
* @param projectType - The type of project template to use ('backend' or 'monorepo')
Expand All @@ -21,6 +62,9 @@ export async function setupTemplate(
const spinner = clack.spinner();
spinner.start('Creating project...');

// Ensure templates are available (extract from zip if needed)
ensureTemplatesExtracted();

const templateDir = join(import.meta.dir, '..', 'templates', projectType);

copyRecursive(templateDir, targetDir, EXCLUDED_COPY_PATTERNS);
Expand Down