Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove email capture, usage tracking #489

Merged
merged 8 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/rich-adults-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"mailing": minor
"mailing-core": minor
---

remove anonymous telemetry and email collection
3 changes: 0 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,3 @@ MAILING_SES_PASSWORD=
MAILING_DATABASE_URL_TEST=
WEB_DATABASE_URL_TEST=
# Note: MAILING_SESSION_PASSWORD must also be set for integration tests to run

## Anonymous telemetry
POSTHOG_API_KEY=
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: yarn jest --rootDir=mailing_tests/jest --config mailing_tests/jest/jest.config.json
working-directory: /tmp/mailing_e2e/ci
- name: Run ${{ matrix.e2e-config }} cypress tests
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v6
env:
DEBUG: "@cypress/github-action"
with:
Expand Down
2 changes: 1 addition & 1 deletion e2e/app/remix_ts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize(root_dir, *args)
def yarn_create!
Dir.chdir(root_dir) do
# install with the "remix" template
system_quiet('yarn create remix . --template=remix --typescript --install')
system_quiet('yarn create remix . --template=remix-run/remix/templates/remix --typescript --install')

## variation: indie-stack is a different remix template that people use
# system_quiet("yarn create remix . --template=remix-run/indie-stack --typescript --install")
Expand Down
1 change: 0 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
"nodemailer": "6.8.0",
"open": "^8.4.0",
"postcss": "^8.4.16",
"posthog-node": "^2.2.3",
"prettier": "^2.7.1",
"prisma": "^4.4.0",
"prompts": "^2.4.2",
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/commands/__test__/exportPreviews.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ describe("exportPreviews command", () => {
typescript: true,
emailsDir: "./packages/cli/src/__mocks__/emails",
outDir: "./previews_html",
anonymousId: "TEST_VALUE",
}));
});

Expand Down
196 changes: 93 additions & 103 deletions packages/cli/src/commands/exportPreviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export type ExportPreviewsArgs = ArgumentsCamelCase<{
outDir?: string;
quiet?: boolean;
minify?: boolean;
anonymousId?: string | null;
skipLint?: boolean;
}>;

Expand Down Expand Up @@ -61,113 +60,104 @@ export function previewFilename(moduleName: string, functionName: string) {
);
}

export const handler = buildHandler(
async (argv: ExportPreviewsArgs) => {
if (!argv.outDir) throw new Error("outDir option is not set");
export const handler = buildHandler(async (argv: ExportPreviewsArgs) => {
if (!argv.outDir) throw new Error("outDir option is not set");

const outDir = argv.outDir;
const outDir = argv.outDir;

if (typeof outDir !== "string") {
error("please specify an outDir like --outDir ./html");
return;
}
if (typeof outDir !== "string") {
error("please specify an outDir like --outDir ./html");
return;
}

if (undefined === argv.emailsDir) {
error("please specific an emailsDir like --emailsDir ./emails");
return;
}
if (undefined === argv.emailsDir) {
error("please specific an emailsDir like --emailsDir ./emails");
return;
}

const previewsPath = getPreviewsDirectory(argv.emailsDir);
if (!previewsPath) {
error(
"Could not find emails directory. Have you initialized the project with `mailing init`?"
);
return;
}

registerRequireHooks();

const previewText = argv.minify ? "minified preview html" : "preview html";

let count = 0;

const lint: { [filename: string]: HtmlLintError[] } = {};
const toWrite: Array<() => Promise<void>> = [];
const filenames: string[] = [];

const previewRenders = readdirSync(previewsPath)
.filter((path) => !/^\./.test(path))
.flatMap((p) => {
const previewPath = resolve(previewsPath, p);
const previewModule = require(previewPath);

return Object.keys(require(previewPath)).flatMap(
async (previewFunction) => {
const filename = previewFilename(p, previewFunction);
count++;

const { html, errors, htmlLint } = render(
await previewModule[previewFunction]()
);
if (errors.length) {
error(`MJML errors rendering ${filename}:`, errors);
}

if (htmlLint.length && !argv.skipLint) {
lint[filename] = htmlLint;
}

const minifyConfig = {
collapseWhitespace: true,
minifyCSS: false,
caseSensitive: true,
removeEmptyAttributes: true,
};

const outHtml = argv.minify
? await minify(html, minifyConfig)
: html;
filenames.push(filename);
toWrite.push(async () =>
outputFile(resolve(outDir, filename), outHtml)
);
const previewsPath = getPreviewsDirectory(argv.emailsDir);
if (!previewsPath) {
error(
"Could not find emails directory. Have you initialized the project with `mailing init`?"
);
return;
}

registerRequireHooks();

const previewText = argv.minify ? "minified preview html" : "preview html";

let count = 0;

const lint: { [filename: string]: HtmlLintError[] } = {};
const toWrite: Array<() => Promise<void>> = [];
const filenames: string[] = [];

const previewRenders = readdirSync(previewsPath)
.filter((path) => !/^\./.test(path))
.flatMap((p) => {
const previewPath = resolve(previewsPath, p);
const previewModule = require(previewPath);

return Object.keys(require(previewPath)).flatMap(
async (previewFunction) => {
const filename = previewFilename(p, previewFunction);
count++;

const { html, errors, htmlLint } = render(
await previewModule[previewFunction]()
);
if (errors.length) {
error(`MJML errors rendering ${filename}:`, errors);
}

if (htmlLint.length && !argv.skipLint) {
lint[filename] = htmlLint;
}
);
});
await Promise.all(previewRenders);

const lintCount = Object.keys(lint).length;
if (lintCount) {
error(
lintCount > 1
? `Aborted because ${lintCount} files have lint errors:`
: `Aborted because 1 file has lint errors:`,
"\n\n",
Object.entries(lint)
.map(
([filename, errors]) =>
`${filename}\n${errors
.map((e, i) => ` ${i + 1}. ${e.message}`)
.join("\n\n")}`
)
.join("\n\n"),
"\n\n"
);

return;
}
const minifyConfig = {
collapseWhitespace: true,
minifyCSS: false,
caseSensitive: true,
removeEmptyAttributes: true,
};

const outHtml = argv.minify ? await minify(html, minifyConfig) : html;
filenames.push(filename);
toWrite.push(async () =>
outputFile(resolve(outDir, filename), outHtml)
);
}
);
});
await Promise.all(previewRenders);

const lintCount = Object.keys(lint).length;
if (lintCount) {
error(
lintCount > 1
? `Aborted because ${lintCount} files have lint errors:`
: `Aborted because 1 file has lint errors:`,
"\n\n",
Object.entries(lint)
.map(
([filename, errors]) =>
`${filename}\n${errors
.map((e, i) => ` ${i + 1}. ${e.message}`)
.join("\n\n")}`
)
.join("\n\n"),
"\n\n"
);

return;
}

log(`Exporting ${previewText} to`);
log(`${outDir}/`);
await Promise.all(toWrite.map((f) => f()));
for (const f of filenames.sort()) {
log(` |-- ${f}`);
}
log(`✅ Processed ${count} previews\n`);
},
{
captureOptions: () => {
return { event: "export-previews invoked" };
},
log(`Exporting ${previewText} to`);
log(`${outDir}/`);
await Promise.all(toWrite.map((f) => f()));
for (const f of filenames.sort()) {
log(` |-- ${f}`);
}
);
log(`✅ Processed ${count} previews\n`);
});
92 changes: 26 additions & 66 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import prompts from "prompts";
import fetch from "node-fetch";
import { existsSync } from "fs-extra";
import { ArgumentsCamelCase } from "yargs";
import { error, log } from "../util/serverLogger";
import { getMailingAPIBaseURL } from "../util/paths";
import { log } from "../util/serverLogger";
import { generateEmailsDirectory } from "../util/generators";
import { handler as previewHandler, PreviewArgs } from "./preview/preview";
import { defaults } from "../util/config";
Expand All @@ -15,7 +12,6 @@ export type InitArguments = ArgumentsCamelCase<{
typescript?: boolean;
port?: number;
quiet?: boolean;
anonymousId?: string | null;
}>;

export const command = ["$0", "init"];
Expand Down Expand Up @@ -53,69 +49,33 @@ export const builder = {
},
};

export const handler = buildHandler(
async (argv: InitArguments) => {
if (typeof argv.port !== "number")
throw new Error("port option is not set");
if (typeof argv.typescript !== "boolean")
throw new Error("typescript option not set");
if (undefined === argv.emailsDir)
throw new Error("emailsDir option not set");
export const handler = buildHandler(async (argv: InitArguments) => {
if (typeof argv.port !== "number") throw new Error("port option is not set");
if (typeof argv.typescript !== "boolean")
throw new Error("typescript option not set");
if (undefined === argv.emailsDir) throw new Error("emailsDir option not set");

if (existsSync(resolve(argv.emailsDir, "previews"))) {
log("Using emails directory", argv.emailsDir);
} else {
const options = {
isTypescript: argv.typescript,
emailsDir: argv.emailsDir,
};
await generateEmailsDirectory(options);

if (argv.scaffoldOnly) {
return;
}

if (!argv.quiet) {
const emailResponse = await prompts({
type: "text",
name: "email",
message:
"enter your email for occasional updates about mailing (optional)",
});
const { email } = emailResponse;
if (email?.length > 0) {
log("great, talk soon");
try {
const url = `${getMailingAPIBaseURL()}/api/newsletterSubscribers`;

void fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
} catch (e) {
error(e);
}
} else {
log("ok, no problem");
}
}
}

const previewHandlerArgv: PreviewArgs = {
port: argv.port,
quiet: argv.quiet,
if (existsSync(resolve(argv.emailsDir, "previews"))) {
log("Using emails directory", argv.emailsDir);
} else {
const options = {
isTypescript: argv.typescript,
emailsDir: argv.emailsDir,
anonymousId: argv.anonymousId,
$0: argv.$0,
_: argv._,
};
await generateEmailsDirectory(options);

await previewHandler(previewHandlerArgv);
},
{
captureOptions: () => {
return { event: "init invoked" };
},
if (argv.scaffoldOnly) {
return;
}
}
);

const previewHandlerArgv: PreviewArgs = {
port: argv.port,
quiet: argv.quiet,
emailsDir: argv.emailsDir,
$0: argv.$0,
_: argv._,
};

await previewHandler(previewHandlerArgv);
});
Loading
Loading