// To install this command while developing run `npm link`. You can rm it // when done. // TODO add integration tests now that the server uses a db. import * as client from '../client/index.js'; import prompts from 'prompts'; import {mustSimpleFetch} from '../client/simple-fetch-node.js'; const tosURL = `https://roci.dev/terms.html`; const tosCommercialDefinitionURL = tosURL + `#software-licenses`; const questionsEmail = `hello@replicache.dev`; const discord = `discord.replicache.dev`; const greeting = `Welcome. Using Replicache requires registering to acquire a license key.\n`; const namePrompt = `Your name:`; const projectPrompt = `Company/project/org name or URL:`; const emailPrompt = `Contact email:`; const commercialPrompt = `Is your project commercial as defined by the Replicache Terms of Service (${tosCommercialDefinitionURL})?`; const tosPrompt = `Do you agree to the Replicache Terms of Service (${tosURL})?`; const sorryTOS = `Sorry, you must agree to the Replicache Terms of Service to use Replicache.`; const fetching = `Fetching License Key...`; const farewell = `Use Replicache like so:\n` + `\n` + `new Replicache({\n` + `\tlicenseKey: "",\n` + `\t...\n` + `});\n` + `\n` + `In unit tests you can pass Replicache.TEST_LICENSE_KEY, which disables license checks for a few minutes.\n` + `\n` + `Questions? ${questionsEmail} or ${discord}.\n`; const issuesURL = `https://github.com/rocicorp/replicache/issues/new`; const thereWasAnError = `Sorry, there was an error. Please file a bug at ${issuesURL} with the following information:\n`; export async function main(licenseServerURL: URL): Promise { await mainImpl(licenseServerURL, client.createCustomer); } export async function mainImpl( licenseServerURL: URL, createCustomer: typeof client.createCustomer, stdout: NodeJS.WritableStream = process.stdout, ): Promise { // Send output directly to stdout. function print(s: string) { stdout.write(s + '\n'); } try { let questions = [ { type: 'text' as prompts.PromptType, name: 'name', message: namePrompt, validate: (name: string) => validateName(name) ? true : 'Name is required', }, { type: 'text' as prompts.PromptType, name: 'project', message: projectPrompt, // Note: no validation, they can leave it empty }, { type: 'text' as prompts.PromptType, name: 'email', message: emailPrompt, validate: (email: string) => validateEmail(email) ? true : 'Email is required', }, { type: 'confirm' as prompts.PromptType, name: 'commercial', message: commercialPrompt, initial: true, }, { type: 'confirm' as prompts.PromptType, name: 'acceptedTOS', message: tosPrompt, initial: false, }, ]; questions = questions.map(q => ({...q, stdout})); print(greeting); const response = await prompts(questions, { onCancel: () => process.exit(1), }); if (response.acceptedTOS) { print(fetching); const licenseKey = await createCustomer( mustSimpleFetch, licenseServerURL, response.name, response.project === '' ? undefined : response.project, response.email, response.commercial, response.acceptedTOS, ); print(`All set! Your License Key:\n\n\t ${licenseKey}\n`); print(farewell); } else { print(sorryTOS); } } catch (e) { print(thereWasAnError + e); process.exit(1); } process.exit(0); } // It's not easy to test validations with the prompts library, so broke these out // to be tested separately. export function validateName(name: string) { return /\S+/.test(name); } export function validateEmail(email: string) { return /^[^@]+@[^@]+\.[^@]+$/.test(email); }