diff --git a/.gitignore b/.gitignore index 4b1db2a..3b6297f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ template/package-lock.json -my-replicate-app \ No newline at end of file +my-replicate-app +foo \ No newline at end of file diff --git a/index.mjs b/index.mjs index e2959b8..4f2788d 100755 --- a/index.mjs +++ b/index.mjs @@ -5,15 +5,18 @@ import path, { dirname } from 'path' import { execSync } from 'child_process' import minimist from 'minimist' import JSON5 from 'json5' +import readline from 'readline' +import { promisify } from 'util' +import open from 'open' // ESM shenanigans for dealing with local files import { fileURLToPath } from 'url' import { getModel, getModelInputs, getModelNameWithVersion } from './lib/models.js' +const readlineSync = await import('readline-sync').then(module => module.default) const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) const argv = minimist(process.argv.slice(2)) - const targetAppName = argv._[0] || 'my-replicate-app' const modelName = argv.model || 'stability-ai/sdxl' @@ -35,6 +38,25 @@ const templateDir = path.join(__dirname, 'template') const targetDir = path.join(process.cwd(), targetAppName) fs.cpSync(templateDir, targetDir, { recursive: true }) +// Get env from existing REPLICATE_API_TOKEN, or prompt user to get it from the browser +const envFile = path.join(targetDir, '.env') + +if (process.env.REPLICATE_API_TOKEN) { + fs.writeFileSync(envFile, `REPLICATE_API_TOKEN=${process.env.REPLICATE_API_TOKEN}`) + console.log('Adding API token to .env file') +} else { + console.log('API token not found in environment.') + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) + const question = promisify(rl.question).bind(rl) + const answer = await question('Open your browser to copy a Replicate API token? (Y/n) ') + if (answer.toLowerCase() === 'y' || answer === '') { + await open('https://replicate.com/account') + const token = readlineSync.question('Paste your API token here: ', { hideEchoBack: true }) + fs.writeFileSync(envFile, `REPLICATE_API_TOKEN=${token}`) + console.log('API token written to .env file') + } +} + console.log('Setting package name...') execSync(`npm pkg set name=${targetAppName}`, { cwd: targetDir, stdio: 'ignore' }) diff --git a/package-lock.json b/package-lock.json index e0bd862..efc04e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,9 @@ "dependencies": { "all-the-public-replicate-models": "^1.97.0", "json5": "^2.2.3", - "minimist": "^1.2.8" + "minimist": "^1.2.8", + "open": "^10.0.3", + "readline-sync": "^1.4.10" }, "bin": { "create-replicate-app": "index.cjs" @@ -33,6 +35,102 @@ "node": ">=18" } }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -51,6 +149,42 @@ "funding": { "url": "https://github.com/sponsors/ljharb" } + }, + "node_modules/open": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.3.tgz", + "integrity": "sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A==", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 878a8da..40946f1 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "dependencies": { "all-the-public-replicate-models": "^1.97.0", "json5": "^2.2.3", - "minimist": "^1.2.8" + "minimist": "^1.2.8", + "open": "^10.0.3", + "readline-sync": "^1.4.10" } } diff --git a/template/.gitignore b/template/.gitignore new file mode 100644 index 0000000..3a0202b --- /dev/null +++ b/template/.gitignore @@ -0,0 +1,2 @@ +.env +.npmrc \ No newline at end of file diff --git a/template/index.js b/template/index.js index d860eb2..878d49b 100644 --- a/template/index.js +++ b/template/index.js @@ -1,4 +1,14 @@ import Replicate from 'replicate' +import dotenv from 'dotenv' +dotenv.config() + +if (!process.env.REPLICATE_API_TOKEN) { + console.error('REPLICATE_API_TOKEN not found in environment') + console.error('To copy a token, go to https://replicate.com/account') + console.error('Then add your token to a local .env file like this:') + console.error('echo "REPLICATE_API_TOKEN=your-token" > .env') + process.exit() +} const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN }) const model = '{{MODEL}}' diff --git a/template/package.json b/template/package.json index 464dfd8..242caa8 100644 --- a/template/package.json +++ b/template/package.json @@ -9,6 +9,7 @@ "start": "node index.js" }, "dependencies": { + "dotenv": "^16.4.1", "replicate": "*" } }