diff --git a/.gitignore b/.gitignore index e9de00a..ec663aa 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ out dist *.tgz +# generated templates archive (created during prepare script) +templates.zip + # code coverage coverage *.lcov diff --git a/bun.lock b/bun.lock index 706f8db..e7c3b35 100644 --- a/bun.lock +++ b/bun.lock @@ -6,9 +6,11 @@ "name": "create-elysiajs", "dependencies": { "@clack/prompts": "^0.11.0", + "adm-zip": "^0.5.16", }, "devDependencies": { "@biomejs/biome": "2.3.10", + "@types/adm-zip": "^0.5.7", "@types/bun": "^1.3.5", }, }, @@ -36,10 +38,14 @@ "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + "@types/adm-zip": ["@types/adm-zip@0.5.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw=="], + "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="], "@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="], + "adm-zip": ["adm-zip@0.5.16", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="], + "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], diff --git a/package.json b/package.json index 5229aa0..2f22a62 100644 --- a/package.json +++ b/package.json @@ -38,10 +38,18 @@ "bin": { "create-ely": "./src/index.ts" }, - "files": ["src", "templates", "README.md", "LICENSE"], + "files": [ + "src", + "templates.zip", + "scripts/postinstall.ts", + "README.md", + "LICENSE" + ], "scripts": { "dev": "bun run src/index.ts", - "build": "bun build src/index.ts --compile --outfile dist/create-ely" + "build": "bun build src/index.ts --compile --outfile dist/create-ely", + "prepare": "bun run scripts/prepare.ts", + "postinstall": "bun run scripts/postinstall.ts" }, "engines": { "bun": ">=1.0.0" @@ -51,10 +59,12 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "@clack/prompts": "^0.11.0" + "@clack/prompts": "^0.11.0", + "adm-zip": "^0.5.16" }, "devDependencies": { "@biomejs/biome": "2.3.10", + "@types/adm-zip": "^0.5.7", "@types/bun": "^1.3.5" } } diff --git a/scripts/postinstall.ts b/scripts/postinstall.ts new file mode 100644 index 0000000..00734ad --- /dev/null +++ b/scripts/postinstall.ts @@ -0,0 +1,43 @@ +#!/usr/bin/env bun +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; +import AdmZip from 'adm-zip'; + +/** + * Postinstall script that runs after package installation + * Unzips the templates folder to restore .gitignore files + * See: https://johnnyreilly.com/smuggling-gitignore-npmrc-in-npm-packages + */ +const templatesPath = join(import.meta.dir, '..', 'templates'); +const zipPath = join(import.meta.dir, '..', 'templates.zip'); + +// Skip if templates folder already exists (source repo or already extracted) +if (existsSync(templatesPath)) { + process.exit(0); +} + +// Zip file must exist in installed package +if (!existsSync(zipPath)) { + console.error( + 'ERROR: templates.zip not found. Installation may be corrupted.', + ); + process.exit(1); +} + +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) { + console.error( + 'ERROR: Failed to extract templates:', + error instanceof Error ? error.message : error, + ); + console.error( + 'Report this issue: https://github.com/truehazker/create-ely/issues', + ); + process.exit(1); +} diff --git a/scripts/prepare.ts b/scripts/prepare.ts new file mode 100644 index 0000000..06bedba --- /dev/null +++ b/scripts/prepare.ts @@ -0,0 +1,42 @@ +#!/usr/bin/env bun +import { existsSync, unlinkSync } from 'node:fs'; +import { join } from 'node:path'; +import AdmZip from 'adm-zip'; + +/** + * Prepare script that runs before publishing + * Zips the templates folder to preserve .gitignore files + * See: https://johnnyreilly.com/smuggling-gitignore-npmrc-in-npm-packages + */ +const templatesPath = join(import.meta.dir, '..', 'templates'); +const zipPath = join(import.meta.dir, '..', 'templates.zip'); + +// Templates folder must exist +if (!existsSync(templatesPath)) { + console.error('ERROR: templates folder not found. Cannot create archive.'); + process.exit(1); +} + +try { + // Remove existing zip if it exists + if (existsSync(zipPath)) { + unlinkSync(zipPath); + } + + // Create zip archive + const zip = new AdmZip(); + zip.addLocalFolder(templatesPath); + zip.writeZip(zipPath); + + if (!existsSync(zipPath)) { + throw new Error('templates.zip was not created'); + } + + console.log('✓ templates.zip created successfully'); +} catch (error) { + console.error( + 'ERROR: Failed to create templates.zip:', + error instanceof Error ? error.message : error, + ); + process.exit(1); +}