diff --git a/CHANGELOG.md b/CHANGELOG.md index e0ed02b..950aa6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.2] - 2026-03-04 + +### Added + +- `isNotionEnabled` toggle in the interactive services prompt (Announcements & Onboarding) +- `isNotionEnabled` flag post-processed in `global.config.ts` alongside the other service flags +- `unoff create` now shows a clear "coming soon" message and exits cleanly for `penpot-plugin`, `sketch-plugin`, and `framer-plugin` instead of attempting scaffold +- `unoff help` now separates available platforms from coming soon platforms +- Service list (Supabase, Mixpanel, Sentry, Notion) displayed in `unoff help` under `create` + +### Changed + +- `.env.local` is now always fully generated with all vars regardless of selected services โ€” only the flags in `global.config.ts` are toggled +- `.env.sentry-build-plugin` is now always generated unconditionally +- README and help output updated to reflect platform availability status + ## [0.1.1] - 2026-03-04 ### Added @@ -43,5 +59,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ๐Ÿšง Sketch plugin template (coming soon) - ๐Ÿšง Framer plugin template (coming soon) +[0.1.2]: https://github.com/yelbolt/unoff-cli/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/yelbolt/unoff-cli/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/yelbolt/unoff-cli/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 4682cdd..de74556 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,25 @@ Show all commands, available platforms, and workers. ### `unoff create ` -Scaffold a new plugin project. Platforms: `figma-plugin`, `penpot-plugin`, `sketch-plugin`, `framer-plugin`. +Scaffold a new plugin project. + +| Platform | Status | +| -------- | ------ | +| `figma-plugin` | โœ… Available | +| `penpot-plugin` | ๐Ÿšง Coming soon | +| `sketch-plugin` | ๐Ÿšง Coming soon | +| `framer-plugin` | ๐Ÿšง Coming soon | + +The interactive prompt will ask for plugin name, output directory, GitHub username, author, license, and which external services to enable: + +| Service | Default | +| ------- | ------- | +| Supabase (Database & Authentication) | โœ… | +| Mixpanel (Analytics) | โœ… | +| Sentry (Error Monitoring) | โœ… | +| Notion (Announcements & Onboarding) | โœ… | + +Selected services update the `is*Enabled` flags in `global.config.ts`. All environment variable placeholders are always generated in `.env.local`. ```bash unoff create figma-plugin @@ -96,9 +114,10 @@ unoff remove announcement-worker ## Features - ๐Ÿš€ Quick setup with interactive CLI -- ๐Ÿ“ฆ Multiple platform support (Figma, Penpot, Sketch, Framer) +- ๐Ÿ“ฆ Multiple platform support (Figma โœ…, Penpot ๐Ÿšง, Sketch ๐Ÿšง, Framer ๐Ÿšง) - ๐Ÿ”ง Built-in development server with hot reload - ๐Ÿ—๏ธ Production-ready build system +- ๐ŸŽ›๏ธ Toggleable external services (Supabase, Mixpanel, Sentry, Notion) - ๐Ÿ” Authentication scaffolding (Supabase) - ๐Ÿ’ณ License management (LemonSqueezy) - ๐Ÿ“Š Analytics and monitoring (Mixpanel, Sentry) diff --git a/package-lock.json b/package-lock.json index 1a1490d..12e7bbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@unoff/cli", - "version": "0.1.1", + "version": "0.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@unoff/cli", - "version": "0.1.1", + "version": "0.1.2", "license": "MIT", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index b29586b..037f6b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@unoff/cli", - "version": "0.1.1", + "version": "0.1.2", "description": "A CLI tool to create plugins for Figma, Penpot, Sketch, and Framer", "main": "dist/index.js", "type": "module", @@ -54,4 +54,4 @@ "type": "git", "url": "https://github.com/yelbolt/unoff-cli.git" } -} \ No newline at end of file +} diff --git a/src/cli.ts b/src/cli.ts index af99ec1..0f3f9e2 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -21,21 +21,26 @@ program .command('create ') .description('Create a new plugin for a specific platform') .action(async (platform: string) => { - const validPlatforms = [ - 'figma-plugin', - 'penpot-plugin', - 'sketch-plugin', - 'framer-plugin', - ] - - if (!validPlatforms.includes(platform)) { + const availablePlatforms = ['figma-plugin'] + const comingSoonPlatforms = ['penpot-plugin', 'sketch-plugin', 'framer-plugin'] + const allPlatforms = [...availablePlatforms, ...comingSoonPlatforms] + + if (!allPlatforms.includes(platform)) { console.error(chalk.red(`\nโŒ Invalid platform: ${platform}`)) console.error( - chalk.yellow(`\nValid platforms: ${validPlatforms.join(', ')}\n`) + chalk.yellow(`\nAvailable platforms: ${availablePlatforms.join(', ')}`) + ) + console.error( + chalk.gray(`Coming soon: ${comingSoonPlatforms.join(', ')}\n`) ) process.exit(1) } + if (comingSoonPlatforms.includes(platform)) { + console.error(chalk.yellow(`\n๐Ÿšง ${platform} template is coming soon!\n`)) + process.exit(0) + } + try { await createPlugin(platform) } catch (error) { diff --git a/src/commands/create.ts b/src/commands/create.ts index 486a692..fde8122 100644 --- a/src/commands/create.ts +++ b/src/commands/create.ts @@ -20,6 +20,7 @@ interface TemplateData { isSupabaseEnabled: boolean isMixpanelEnabled: boolean isSentryEnabled: boolean + isNotionEnabled: boolean } function slugify(text: string): string { @@ -133,6 +134,11 @@ export async function createPlugin(platform: string) { value: 'sentry', checked: true, }, + { + name: 'Notion (Announcements & Onboarding)', + value: 'notion', + checked: true, + }, ], }, ]) @@ -206,6 +212,7 @@ export async function createPlugin(platform: string) { isSupabaseEnabled: selectedServices.includes('supabase'), isMixpanelEnabled: selectedServices.includes('mixpanel'), isSentryEnabled: selectedServices.includes('sentry'), + isNotionEnabled: selectedServices.includes('notion'), } // Copy template directory excluding node_modules and dist @@ -248,6 +255,10 @@ export async function createPlugin(platform: string) { /isSentryEnabled: true/, `isSentryEnabled: ${templateData.isSentryEnabled}` ) + .replace( + /isNotionEnabled: true/, + `isNotionEnabled: ${templateData.isNotionEnabled}` + ) await fs.writeFile(globalConfigPath, configContent, 'utf-8') } @@ -362,41 +373,28 @@ async function generateEnvFiles(outputDir: string, templateData: TemplateData) { const envSentryPath = path.join(outputDir, '.env.sentry-build-plugin') // Generate .env.local content - let envLocalContent = '' - - if (templateData.isSupabaseEnabled) { - envLocalContent += ` + const envLocalContent = ` # Supabase Configuration # Get your keys from: https://supabase.com/dashboard/project/_/settings/api VITE_SUPABASE_URL='YOUR_SUPABASE_URL' VITE_SUPABASE_PUBLIC_ANON_KEY='YOUR_SUPABASE_ANON_KEY' -` - } - - if (templateData.isSentryEnabled) { - envLocalContent += ` # Sentry Configuration # Get your DSN from: https://sentry.io/settings/projects/ VITE_SENTRY_DSN='YOUR_SENTRY_DSN' -` - } - - if (templateData.isMixpanelEnabled) { - envLocalContent += ` # Mixpanel Configuration # Get your token from: https://mixpanel.com/settings/project/ VITE_MIXPANEL_TOKEN='YOUR_MIXPANEL_TOKEN' -` - } - - // Add common configuration - envLocalContent += ` # Authentication & Workers VITE_AUTH_URL='https://auth.${templateData.pluginSlug}.com' +# Workers URLs +VITE_AUTH_WORKER_URL='https://oauth.yelbolt.workers.dev' +VITE_CORS_WORKER_URL='https://cors.yelbolt.workers.dev' +VITE_ANNOUNCEMENTS_WORKER_URL='https://68e83449-announcements.yelbolt.workers.dev/' + # Notion โ€” Content Management (Announcements & Onboarding) # Duplicate the databases to your Notion workspace and paste their IDs below # Create an internal integration at https://www.notion.so/my-integrations and add it to both databases @@ -404,11 +402,6 @@ VITE_NOTION_ANNOUNCEMENTS_ID='YOUR_ANNOUNCEMENTS_DB_ID' VITE_NOTION_ONBOARDING_ID='YOUR_ONBOARDING_DB_ID' VITE_NOTION_API_KEY='YOUR_NOTION_API_KEY' -# Workers URLs -VITE_AUTH_WORKER_URL='https://oauth.yelbolt.workers.dev' -VITE_ANNOUNCEMENTS_WORKER_URL='https://68e83449-announcements.yelbolt.workers.dev/' -VITE_CORS_WORKER_URL='https://cors.yelbolt.workers.dev' - # LemonSqueezy (if using payments) # You can test with this test license key: 0DE7C002-1F28-49E8-A444-B424F346416E VITE_LEMONSQUEEZY_URL='https://api.lemonsqueezy.com/v1' @@ -421,12 +414,10 @@ VITE_TOLGEE_API_KEY='YOUR_TOLGEE_API_KEY' await fs.writeFile(envLocalPath, envLocalContent, 'utf-8') - // Generate .env.sentry-build-plugin only if Sentry is enabled - if (templateData.isSentryEnabled) { - const envSentryContent = `# Sentry Build Plugin Configuration + // Generate .env.sentry-build-plugin + const envSentryContent = `# Sentry Build Plugin Configuration # Generate your auth token from: https://sentry.io/settings/account/api/auth-tokens/ SENTRY_AUTH_TOKEN='YOUR_SENTRY_AUTH_TOKEN' ` - await fs.writeFile(envSentryPath, envSentryContent, 'utf-8') - } + await fs.writeFile(envSentryPath, envSentryContent, 'utf-8') } diff --git a/src/commands/help.ts b/src/commands/help.ts index 1da003c..118d956 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,7 +1,19 @@ import chalk from 'chalk' import { WORKERS, WORKER_SCRIPTS } from './add.js' -const PLATFORMS = ['figma-plugin', 'penpot-plugin', 'sketch-plugin', 'framer-plugin'] +const AVAILABLE_PLATFORMS = ['figma-plugin'] +const COMING_SOON_PLATFORMS = [ + 'penpot-plugin', + 'sketch-plugin', + 'framer-plugin', +] + +const SERVICES = [ + { name: 'supabase', label: 'Supabase (Database & Authentication)' }, + { name: 'mixpanel', label: 'Mixpanel (Analytics)' }, + { name: 'sentry', label: 'Sentry (Error Monitoring)' }, + { name: 'notion', label: 'Notion (Announcements & Onboarding)' }, +] function row(cmd: string, desc: string) { return ` ${chalk.cyan(cmd.padEnd(36))}${chalk.white(desc)}` @@ -32,7 +44,18 @@ export function showHelp() { 'Scaffold a new plugin project' ) ) - console.log(chalk.gray(` ${''.padEnd(36)}Platforms: ${PLATFORMS.join(', ')}`)) + console.log( + chalk.gray(` ${''.padEnd(36)}Available: ${AVAILABLE_PLATFORMS.join(', ')}`) + ) + console.log( + chalk.gray( + ` ${''.padEnd(36)}Coming soon: ${COMING_SOON_PLATFORMS.join(', ')}` + ) + ) + console.log(chalk.gray(` ${''.padEnd(36)}Services (toggleable, all enabled by default):`)) + for (const s of SERVICES) { + console.log(chalk.gray(` ${''.padEnd(38)}ยท ${s.label}`)) + } console.log() console.log(chalk.dim(' โ€” Development'))