feat: set up CI auto publish

This commit is contained in:
veganbeef 2025-07-12 15:21:50 -07:00
parent 5fa624a063
commit fb4f8b8b53
No known key found for this signature in database
4 changed files with 115 additions and 47 deletions

30
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Publish to npm 🚀
on:
push:
branches:
- main
paths:
- package.json
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Install dependencies
run: npm ci
- name: Publish to npm
run: npm publish --access public

View File

@ -6,6 +6,7 @@ import { init } from './init.js';
const args = process.argv.slice(2); const args = process.argv.slice(2);
let projectName = null; let projectName = null;
let autoAcceptDefaults = false; let autoAcceptDefaults = false;
let apiKey = null;
// Check for -y flag // Check for -y flag
const yIndex = args.indexOf('-y'); const yIndex = args.indexOf('-y');
@ -14,18 +15,48 @@ if (yIndex !== -1) {
args.splice(yIndex, 1); // Remove -y from args args.splice(yIndex, 1); // Remove -y from args
} }
// If there's a remaining argument, it's the project name // Parse other arguments
if (args.length > 0) { for (let i = 0; i < args.length; i++) {
projectName = args[0]; const arg = args[i];
}
if (arg === '-p' || arg === '--project') {
if (i + 1 < args.length) {
projectName = args[i + 1];
if (projectName.startsWith('-')) {
console.error('Error: Project name cannot start with a dash (-)');
process.exit(1);
}
args.splice(i, 2); // Remove both the flag and its value
i--; // Adjust index since we removed 2 elements
} else {
console.error('Error: -p/--project requires a project name');
process.exit(1);
}
} else if (arg === '-k' || arg === '--api-key') {
if (i + 1 < args.length) {
apiKey = args[i + 1];
if (apiKey.startsWith('-')) {
console.error('Error: API key cannot start with a dash (-)');
process.exit(1);
}
args.splice(i, 2); // Remove both the flag and its value
i--; // Adjust index since we removed 2 elements
} else {
console.error('Error: -k/--api-key requires an API key');
process.exit(1);
}
}
}
// If -y is used without project name, we still need to ask for project name
// Validate that if -y is used, a project name must be provided
if (autoAcceptDefaults && !projectName) { if (autoAcceptDefaults && !projectName) {
// We'll handle this case in the init function by asking only for project name console.error('Error: -y flag requires a project name. Use -p/--project to specify the project name.');
autoAcceptDefaults = false; process.exit(1);
} }
init(projectName, autoAcceptDefaults).catch((err) => { init(projectName, autoAcceptDefaults, apiKey).catch((err) => {
console.error('Error:', err); console.error('Error:', err);
process.exit(1); process.exit(1);
}); });

View File

@ -63,7 +63,7 @@ async function queryNeynarApp(apiKey) {
} }
// Export the main CLI function for programmatic use // Export the main CLI function for programmatic use
export async function init(projectName = null, autoAcceptDefaults = false) { export async function init(projectName = null, autoAcceptDefaults = false, apiKey = null) {
printWelcomeMessage(); printWelcomeMessage();
// Ask about Neynar usage // Ask about Neynar usage
@ -101,52 +101,59 @@ export async function init(projectName = null, autoAcceptDefaults = false) {
break; break;
} }
console.log( // Use provided API key if available, otherwise prompt for it
'\n🪐 Find your Neynar API key at: https://dev.neynar.com/app\n' if (apiKey) {
); neynarApiKey = apiKey;
let neynarKeyAnswer;
if (autoAcceptDefaults) {
neynarKeyAnswer = { neynarApiKey: null };
} else { } else {
neynarKeyAnswer = await inquirer.prompt([ if (!autoAcceptDefaults) {
{ console.log(
type: 'password', '\n🪐 Find your Neynar API key at: https://dev.neynar.com/app\n'
name: 'neynarApiKey', );
message: 'Enter your Neynar API key (or press enter to skip):', }
default: null,
},
]);
}
if (neynarKeyAnswer.neynarApiKey) { let neynarKeyAnswer;
neynarApiKey = neynarKeyAnswer.neynarApiKey;
} else {
let useDemoKey;
if (autoAcceptDefaults) { if (autoAcceptDefaults) {
useDemoKey = { useDemo: true }; neynarKeyAnswer = { neynarApiKey: null };
} else { } else {
useDemoKey = await inquirer.prompt([ neynarKeyAnswer = await inquirer.prompt([
{ {
type: 'confirm', type: 'password',
name: 'useDemo', name: 'neynarApiKey',
message: 'Would you like to try the demo Neynar API key?', message: 'Enter your Neynar API key (or press enter to skip):',
default: true, default: null,
}, },
]); ]);
} }
if (useDemoKey.useDemo) { if (neynarKeyAnswer.neynarApiKey) {
console.warn( neynarApiKey = neynarKeyAnswer.neynarApiKey;
'\n⚠ Note: the demo key is for development purposes only and is aggressively rate limited.' } else {
); let useDemoKey;
console.log( if (autoAcceptDefaults) {
'For production, please sign up for a Neynar account at https://neynar.com/ and configure the API key in your .env or .env.local file with NEYNAR_API_KEY.' useDemoKey = { useDemo: true };
); } else {
console.log( useDemoKey = await inquirer.prompt([
`\n${purple}${bright}${italic}Neynar now has a free tier! See https://neynar.com/#pricing for details.\n${reset}` {
); type: 'confirm',
neynarApiKey = 'FARCASTER_V2_FRAMES_DEMO'; name: 'useDemo',
message: 'Would you like to try the demo Neynar API key?',
default: true,
},
]);
}
if (useDemoKey.useDemo) {
console.warn(
'\n⚠ Note: the demo key is for development purposes only and is aggressively rate limited.'
);
console.log(
'For production, please sign up for a Neynar account at https://neynar.com/ and configure the API key in your .env or .env.local file with NEYNAR_API_KEY.'
);
console.log(
`\n${purple}${bright}${italic}Neynar now has a free tier! See https://neynar.com/#pricing for details.\n${reset}`
);
neynarApiKey = 'FARCASTER_V2_FRAMES_DEMO';
}
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@neynar/create-farcaster-mini-app", "name": "@neynar/create-farcaster-mini-app",
"version": "1.5.8", "version": "1.5.9",
"type": "module", "type": "module",
"private": false, "private": false,
"access": "public", "access": "public",